Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env sh
#
# DCP pre-push guard.
#
# OSS must never push private/premium code (one-way dependency: private -> OSS).
# This runs the publish guard, which (a) verifies package publish config and
# (b) scans tracked files for premium markers. A non-zero exit blocks the push.
#
# Bypass (use only when you are SURE): git push --no-verify

set -e

echo "[pre-push] Running DCP publish guard (premium-leak + publish-config check)..."

# Resolve repo root so the hook works regardless of CWD.
ROOT="$(git rev-parse --show-toplevel)"

if ! node "$ROOT/scripts/publish-guard.mjs"; then
echo ""
echo "[pre-push] BLOCKED: publish guard failed. Fix the issues above before pushing."
echo "[pre-push] (Override only if you are certain: git push --no-verify)"
exit 1
fi

echo "[pre-push] Publish guard passed."
11 changes: 0 additions & 11 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,6 @@ updates:
interval: monthly
open-pull-requests-limit: 1

- package-ecosystem: cargo
directory: /packages/dcp-desktop/src-tauri
schedule:
interval: monthly
open-pull-requests-limit: 2
groups:
cargo-minor-and-patch:
update-types:
- minor
- patch

- package-ecosystem: pip
directory: /sdks/python
schedule:
Expand Down
172 changes: 0 additions & 172 deletions .github/workflows/build-desktop.yml

This file was deleted.

5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,8 @@ temp/
# Local test configs (may contain secrets)
test-*.json
*.local.json

# Operator-specific deployment configs (our hosted infra — not part of OSS).
# Self-hosters: copy fly.toml.example / fly.telegram.toml.example and set your own app name.
fly.toml
fly.telegram.toml
12 changes: 11 additions & 1 deletion fly.telegram.toml → fly.telegram.toml.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
app = 'telegram-dcp-1lystore'
# fly.telegram.toml — example Fly.io config for self-hosting the DCP Telegram service.
#
# Copy to `fly.telegram.toml`, set your own `app` name, then deploy with:
# fly deploy -c fly.telegram.toml
# `fly.telegram.toml` is gitignored so your deployment config stays private.
#
# Bring your OWN Telegram bot token (from @BotFather):
# fly secrets set DCP_TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
# See https://fly.io/docs/reference/configuration/

app = 'your-dcp-telegram-app'
primary_region = 'iad'

[build]
Expand Down
23 changes: 0 additions & 23 deletions fly.toml

This file was deleted.

24 changes: 24 additions & 0 deletions fly.toml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# fly.toml — example Fly.io config for self-hosting the DCP relay.
#
# Copy to `fly.toml`, set your own `app` name, then `fly deploy`.
# `fly.toml` is gitignored so your deployment config stays private.
# See https://fly.io/docs/reference/configuration/

app = 'your-dcp-relay-app'
primary_region = 'iad'

[build]

[http_service]
internal_port = 8422
force_https = true
auto_stop_machines = 'stop'
auto_start_machines = true
min_machines_running = 0
processes = ['app']

[[vm]]
memory = '1gb'
cpu_kind = 'shared'
cpus = 1
memory_mb = 1024
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"packageManager": "pnpm@9.15.0",
"scripts": {
"preinstall": "node scripts/check-node-version.mjs && npx only-allow pnpm",
"prepare": "git config core.hooksPath .githooks || true",
"build": "pnpm -r --filter @dcprotocol/core run build && pnpm -r run build",
"dev:cli": "pnpm -r --filter @dcprotocol/core run build && pnpm --filter @dcprotocol/vault run dev --",
"test": "pnpm -r run test",
Expand Down
7 changes: 5 additions & 2 deletions packages/dcp-agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,19 @@
"author": "DCP Protocol",
"license": "Apache-2.0",
"dependencies": {
"@dcprotocol/core": "^2.0.1",
"@dcprotocol/client": "^2.0.1",
"@dcprotocol/core": "^2.0.1",
"@modelcontextprotocol/sdk": "^1.0.0",
"@noble/curves": "^1.4.0",
"@solana/web3.js": "^1.98.0",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"ora": "^8.0.1"
"ora": "^8.0.1",
"qrcode-terminal": "^0.12.0"
},
"devDependencies": {
"@types/node": "^22.10.2",
"@types/qrcode-terminal": "^0.12.2",
"tsup": "^8.3.5",
"tsx": "^4.19.2",
"typescript": "^5.7.2",
Expand Down
52 changes: 51 additions & 1 deletion packages/dcp-agent/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
generateSigningKeyPair,
type SignedPairingGrant,
} from '@dcprotocol/core';
import { AgentConfig, AgentError } from './types.js';
import { AgentConfig, AgentError, type MobilePairingApprovalStatus, type MobilePendingConfig } from './types.js';

// ============================================================================
// Constants
Expand Down Expand Up @@ -151,6 +151,56 @@ export function saveConfig(config: AgentConfig): void {
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 0o600 });
}

/**
* Save pending mobile pairing material.
*
* This is not a usable AgentConfig yet. The mobile vault must approve the
* invite and return vault identity before this can be promoted to a runtime
* agent config.
*/
export function saveMobilePendingConfig(config: MobilePendingConfig): void {
ensureConfigDir();
const safeInviteId = config.invite_id.replace(/[^a-zA-Z0-9_-]/g, '_');
const configPath = path.join(CONFIG_DIR, `${safeInviteId}.mobile-pending.json`);
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 0o600 });
}

export function promoteMobilePendingConfig(
pending: MobilePendingConfig,
approval: MobilePairingApprovalStatus
): AgentConfig {
if (
approval.status !== 'approved' ||
!approval.agent_id ||
!approval.vault_id ||
!approval.vault_hpke_public_key ||
!approval.vault_signing_public_key
) {
throw new AgentError('INVALID_GRANT', 'Mobile pairing approval is incomplete');
}

const config: AgentConfig = {
agent_id: approval.agent_id,
agent_name: pending.invite.agent_name,
vault_id: approval.vault_id,
mode: 'mcp',
vault_hpke_public_key: approval.vault_hpke_public_key,
vault_signing_public_key: approval.vault_signing_public_key,
relay_url: pending.invite.relay_url,
service_keypair: pending.service_keypair,
paired_at: new Date().toISOString(),
grant_expires_at: pending.invite.expires_at,
};

saveConfig(config);
const safeInviteId = pending.invite_id.replace(/[^a-zA-Z0-9_-]/g, '_');
const pendingPath = path.join(CONFIG_DIR, `${safeInviteId}.mobile-pending.json`);
if (fs.existsSync(pendingPath)) {
fs.unlinkSync(pendingPath);
}
return config;
}

/**
* Load agent configuration
*
Expand Down
Loading
Loading