From 5a8804b03bd507c25b8cb29eecfaec6df5ab9f88 Mon Sep 17 00:00:00 2001 From: Alex Godoroja Date: Tue, 7 Jul 2026 16:06:47 -0700 Subject: [PATCH 1/4] app-store: add io.pilot.didit card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the Didit identity-verification platform to the app-store data — KYC/ID, liveness, face match, AML, proof-of-address, database validation, email/phone OTP + hosted sessions, workflows, billing, blocklist, questionnaires, users, webhooks (39 methods + didit.help). byo HTTPS app with no-broker self-signup (didit.signup + didit.verify mint and cache a per-user Didit key locally). Security category; Didit brand icon added. --- public/appicons/io.pilot.didit.png | Bin 0 -> 9220 bytes src/data/apps.ts | 254 +++++++++++++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 public/appicons/io.pilot.didit.png diff --git a/public/appicons/io.pilot.didit.png b/public/appicons/io.pilot.didit.png new file mode 100644 index 0000000000000000000000000000000000000000..043c4761d1c9a631a063990a86a0e10620a5f5d2 GIT binary patch literal 9220 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 a(f Date: Tue, 7 Jul 2026 17:08:41 -0700 Subject: [PATCH 2/4] =?UTF-8?q?app-store:=20io.pilot.didit=20=E2=86=92=20o?= =?UTF-8?q?ne-call=20broker=20signup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit didit.signup {} now mints the Didit key in one call (no email, no code) via Pilot's broker; adds didit.account; updates description, methods, grants. --- src/data/apps.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/data/apps.ts b/src/data/apps.ts index 44ec5d2..cdcaf49 100644 --- a/src/data/apps.ts +++ b/src/data/apps.ts @@ -2348,7 +2348,7 @@ export const apps: App[] = [ "id": "io.pilot.didit", "name": "Didit", "tagline": "One API for identity and fraud \u2014 KYC, liveness, face match, AML, and more, with a no-broker key you mint in one call.", - "description": "**Didit is one API for identity and fraud** \u2014 KYC/ID verification, liveness, face match, AML screening, proof of address, database validation, and email/phone OTP, wrapped as a single Pilot app. It fronts Didit's full platform: **hosted verification sessions**, reusable **workflows**, **users**, **billing**, **blocklists**, **questionnaires**, and **webhooks** \u2014 40 methods in all.\n\n## No broker \u2014 your own key, minted in two calls\n\nUnlike managed apps, this app holds **no shared key** and routes through **no Pilot broker**. Instead it self-provisions a Didit account that is entirely *yours*, keyed by *your* email:\n\n1. **`didit.signup` `{email}`** registers you with Didit; Didit emails your inbox a 6-character code. (Use a real inbox \u2014 Didit rejects disposable mailboxes. The account email + password are cached locally so the account stays recoverable.)\n2. **`didit.verify` `{code}`** confirms the code and writes the returned `api_key` to `$APP/secrets.json`.\n\nAfter that, **every other method sends your key as `x-api-key` automatically** \u2014 you never handle it. Verifications bill to **your** Didit balance (top up with `didit.billing_topup`); Pilot adds no markup and sees no credentials. Each new account includes Didit's **500 free full-KYC checks/month**, and account creation, management, sessions CRUD, users, billing, blocklists, questionnaires and webhooks are all **free** \u2014 you only pay per verification you actually run.\n\n## The fast path\n\n1. `didit.signup` `{email:\"you@example.com\"}` \u2192 check that inbox for the code.\n2. `didit.verify` `{code:\"A3K9F2\"}` \u2192 your key is cached.\n3. `didit.create_workflow` `{workflow_label:\"KYC\", features:[{feature:\"OCR\"},{feature:\"LIVENESS\"},{feature:\"FACE_MATCH\"}]}` \u2192 get `uuid`.\n4. `didit.create_session` `{workflow_id, vendor_data:\"user-123\"}` \u2192 send the user to the returned `url`.\n5. `didit.get_decision` `{session_id}` (or a webhook) \u2192 read the Approved/Declined result and extracted data.\n\n## What each area does\n\n- **Sessions** \u2014 hosted flows where the user completes verification at a Didit URL, so you never handle document images: `create_session`, `get_decision`, `list_sessions`, `update_session_status` (approve/decline/resubmit), `delete_session`, `batch_delete_sessions`, `share_session` / `import_session` (B2B KYC reuse), `list_reviews`, `create_review`.\n- **Workflows** \u2014 templates built from an ordered `features` array (`OCR`, `LIVENESS`, `FACE_MATCH`, `AML`, `PROOF_OF_ADDRESS`, `PHONE_VERIFICATION`, `EMAIL_VERIFICATION`, `DATABASE_VALIDATION`, `IP_ANALYSIS`, `AGE_ESTIMATION`, `NFC`, `QUESTIONNAIRE`, `KYB_*`), each with an optional per-feature `config`: `create_workflow`, `list_workflows`, `get_workflow`, `update_workflow`, `delete_workflow`.\n- **Standalone checks (JSON, no session)** \u2014 `aml` (sanctions/PEP/adverse-media, $0.20), `database_validation` (gov sources, from $0.05).\n- **Contact** \u2014 `email_send`/`email_check` ($0.03) and `phone_send`/`phone_check` (from $0.03) OTP verification.\n- **Billing** \u2014 `billing_balance`, `billing_topup` (Stripe checkout URL).\n- **Governance** \u2014 `blocklist_*` (auto-flag repeat faces/docs/phones/emails), `questionnaire_*` (custom forms), `users_*` (people grouped by your `vendor_data`), `get_webhook`/`update_webhook` (set + rotate the HMAC secret programmatically).\n\n## Pricing\n\nPay-per-check on **your** Didit balance \u2014 no Pilot markup. See the full rate card in `didit.help`. Highlights: full KYC bundle **$0.33/check** (first **500/month free**), ID verification $0.15, passive liveness $0.10, face match $0.05, **face search free**, AML $0.20, PoA $0.20, email/phone from $0.03. Image-upload APIs (direct ID scan, liveness, face match, face search, age estimation, PoA) run through the **hosted session** flow rather than as direct methods.\n\n## Notes\n\n- Two hosts, one app: signup uses `apx.didit.me`; everything else uses `verification.didit.me`. The adapter only ever dials Didit and the temp-mail provider used for the one-time OTP.\n- Plain request/response REST \u2014 no websockets, no async jobs. Rate limits: ~600 session-creates/min, 300/min per other method; the account OTP register is 5/IP/hour.\n- Errors surface verbatim: `401` (run `didit.signup` first), `403` (top up credits), `429` (back off).\n", + "description": "**Didit is one API for identity and fraud** \u2014 KYC/ID verification, liveness, face match, AML screening, proof of address, database validation, and email/phone OTP, wrapped as a single Pilot app. It fronts Didit's full platform: **hosted verification sessions**, reusable **workflows**, **users**, **billing**, **blocklists**, **questionnaires**, and **webhooks** \u2014 40 methods in all.\n\n## Your own key, minted in one call \u2014 no email, no code\n\nThe hard part of using an identity provider is usually onboarding: signing up, confirming an email code, and wiring the key. This app removes all of it. **`didit.signup` takes no arguments** and returns a working key:\n\n- It signs a keyless request (your Pilot identity) to Pilot's Didit broker. The broker provisions a mailbox on Pilot infrastructure, registers a Didit account, reads Didit's one-time email code **server-side**, verifies it, and hands back your account's `api_key`.\n- The adapter caches `{email, api_key}` to `$APP/secrets.json`. From then on **every other method sends your key as `x-api-key` automatically** \u2014 you never see an inbox, a code, or the key unless you ask (`didit.account`).\n- **Idempotent:** the broker mints at most one Didit account per Pilot identity, so a repeat call \u2014 or a fresh install on another machine \u2014 returns the *same* account. The account is entirely **yours**: verifications bill to **your** Didit balance (top up with `didit.billing_topup`), and Pilot adds no markup. Each account includes Didit's **500 free full-KYC checks/month**; account creation, management, sessions CRUD, users, billing, blocklists, questionnaires and webhooks are all **free** \u2014 you pay only per verification you run.\n\n## The fast path\n\n1. `didit.signup {}` \u2192 your key is cached (one call, ~5s, no email).\n2. `didit.create_workflow` `{workflow_label:\"KYC\", features:[{feature:\"OCR\"},{feature:\"LIVENESS\"},{feature:\"FACE_MATCH\"}]}` \u2192 get `uuid`.\n3. `didit.create_session` `{workflow_id, vendor_data:\"user-123\"}` \u2192 send the user to the returned `url`.\n4. `didit.get_decision` `{session_id}` (or a webhook) \u2192 read the Approved/Declined result and extracted data.\n\n`didit.account` returns your provisioned email + key any time.\n\n## What each area does\n\n- **Sessions** \u2014 hosted flows where the user completes verification at a Didit URL, so you never handle document images: `create_session`, `get_decision`, `list_sessions`, `update_session_status` (approve/decline/resubmit), `delete_session`, `batch_delete_sessions`, `share_session` / `import_session` (B2B KYC reuse), `list_reviews`, `create_review`.\n- **Workflows** \u2014 templates built from an ordered `features` array (`OCR`, `LIVENESS`, `FACE_MATCH`, `AML`, `PROOF_OF_ADDRESS`, `PHONE_VERIFICATION`, `EMAIL_VERIFICATION`, `DATABASE_VALIDATION`, `IP_ANALYSIS`, `AGE_ESTIMATION`, `NFC`, `QUESTIONNAIRE`, `KYB_*`), each with an optional per-feature `config`: `create_workflow`, `list_workflows`, `get_workflow`, `update_workflow`, `delete_workflow`.\n- **Standalone checks (JSON, no session)** \u2014 `aml` (sanctions/PEP/adverse-media, $0.20), `database_validation` (gov sources, from $0.05).\n- **Contact** \u2014 `email_send`/`email_check` ($0.03) and `phone_send`/`phone_check` (from $0.03) OTP verification.\n- **Billing** \u2014 `billing_balance`, `billing_topup` (Stripe checkout URL).\n- **Governance** \u2014 `blocklist_*` (auto-flag repeat faces/docs/phones/emails), `questionnaire_*` (custom forms), `users_*` (people grouped by your `vendor_data`), `get_webhook`/`update_webhook` (set + rotate the HMAC secret programmatically).\n\n## Pricing\n\nPay-per-check on **your** Didit balance \u2014 no Pilot markup. See the full rate card in `didit.help`. Highlights: full KYC bundle **$0.33/check** (first **500/month free**), ID verification $0.15, passive liveness $0.10, face match $0.05, **face search free**, AML $0.20, PoA $0.20, email/phone from $0.03. Image-upload APIs (direct ID scan, liveness, face match, face search, age estimation, PoA) run through the **hosted session** flow rather than as direct methods.\n\n## Notes\n\n- The adapter dials exactly two hosts: Pilot's broker (`broker.pilotprotocol.network`) for the one-call `didit.signup`, and Didit (`verification.didit.me`) for every operational call with your cached key. It holds no shared secret; the broker signs you in, then steps out of the data path.\n- Plain request/response REST \u2014 no websockets, no async jobs. Rate limits: ~600 session-creates/min, 300/min per other method; the account OTP register is 5/IP/hour.\n- Errors surface verbatim: `401` (run `didit.signup` first), `403` (top up credits), `429` (back off).\n", "categories": [ "security" ], @@ -2379,11 +2379,11 @@ export const apps: App[] = [ "methods": [ { "name": "didit.signup", - "summary": "STEP 1 of 2 \u2014 create a Didit account. Pass YOUR email; Didit emails it a 6-character one-time code. No broker: this hits Didit's programmatic register endpoint (POST /programmatic/register/) directly and caches the account email + password to $APP/secrets.json so the account stays recoverable. It does NOT return an API key \u2014 Didit only issues the key after you confirm the code. Then call didit.verify with that code. Why your own email (not a throwaway): Didit suppresses disposable mailboxes, so the code must land in an inbox you control. FREE \u2014 account creation costs nothing; you pay only per verification you run, and each new account includes Didit's 500 free full-KYC checks/month. Register is rate-limited to 5 attempts per IP per hour. Password is optional (a strong one is generated and cached if omitted)." + "summary": "Get your own Didit API key in ONE call \u2014 no email, no code, no human step. This signs a keyless request to Pilot's Didit broker, which provisions a mailbox on Pilot infrastructure, registers a Didit account, reads the emailed one-time code server-side, verifies it, and returns your account's api_key. The adapter caches {email, api_key} to $APP/secrets.json, and from then on EVERY other didit.* method authenticates automatically (x-api-key) \u2014 you never handle the key or an inbox. Idempotent: the broker mints at most one account per Pilot identity, so a repeat call (or a fresh install) returns the SAME account. Run this ONCE before any other method. FREE \u2014 account creation costs nothing; you pay only per verification you run, and each account includes Didit's 500 free full-KYC checks/month. The account (email + key) is retrievable any time via didit.account. Takes no arguments." }, { - "name": "didit.verify", - "summary": "STEP 2 of 2 \u2014 confirm the code from didit.signup and mint your API key. Pass the 6-character code Didit emailed you; this POSTs to /programmatic/verify-email/, extracts application.api_key from the response, and writes it to $APP/secrets.json as DIDIT_API_KEY. From then on EVERY other didit.* method authenticates automatically (x-api-key) \u2014 you never handle the key yourself. Idempotent: if a key is already cached it returns {already:true} without re-verifying. email defaults to the address you registered with, so usually you only need to pass {code}. FREE." + "name": "didit.account", + "summary": "Retrieve your cached Didit account \u2014 the email the broker provisioned for you and your api_key \u2014 plus a signed_up flag. Local, instant, FREE (reads $APP/secrets.json; no backend call). Use it to confirm you're signed up or to read your key. If signed_up is false, call didit.signup first." }, { "name": "didit.billing_balance", @@ -2543,8 +2543,8 @@ export const apps: App[] = [ "version": "1.0.0", "notes": [ "Initial release \u2014 the full Didit identity platform over one byo HTTPS app: 39 methods + didit.help.", - "No-broker self-signup: didit.signup {email} + didit.verify {code} mint and cache a per-user Didit API key locally; every method then authenticates as you.", - "KYC/ID, liveness, face match, AML, proof-of-address, database validation, email/phone OTP, hosted sessions, workflows, billing, blocklist, questionnaires, users, webhooks \u2014 with per-endpoint pricing in didit.help." + "One-call broker signup: didit.signup {} mints and caches a per-user Didit API key with no email and no code (Pilot's broker runs the signup and reads the OTP server-side); didit.account retrieves it; ops stay direct to Didit.", + "KYC/ID, liveness, face match, AML, proof-of-address, database validation, email/phone OTP, hosted sessions, workflows, billing, blocklist, questionnaires, users, webhooks \u2014 per-endpoint pricing in didit.help." ] } ], @@ -2552,29 +2552,30 @@ export const apps: App[] = [ "fs.read:$APP/config.json", "fs.read:$APP/secrets.json", "fs.write:$APP/secrets.json", + "key.sign:self", "net.dial:verification.didit.me", - "net.dial:apx.didit.me", + "net.dial:broker.pilotprotocol.network", "audit.log:*" ], "bundles": [ { "platform": "darwin-arm64", - "bytes": 4939105 + "bytes": 4954879 }, { "platform": "darwin-amd64", - "bytes": 5267882 + "bytes": 5287106 }, { "platform": "linux-arm64", - "bytes": 4682890 + "bytes": 4696257 }, { "platform": "linux-amd64", - "bytes": 5110122 + "bytes": 5130067 } ], - "installedBytes": 9287497, + "installedBytes": 9324763, "depends": [], "protection": "shareable", "featured": false, @@ -2595,7 +2596,7 @@ export const apps: App[] = [ "go" ], "publishedAt": "2026-07-07", - "updatedAt": "2026-07-07" + "updatedAt": "2026-07-08" } ]; From c6bc50582fbc7460bb0c3564125f93e06b70cf41 Mon Sep 17 00:00:00 2001 From: Alex Godoroja Date: Tue, 7 Jul 2026 17:16:28 -0700 Subject: [PATCH 3/4] app-store: pin Didit in New & Updated --- src/pages/app-store.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/app-store.astro b/src/pages/app-store.astro index ef2d287..2546eb7 100644 --- a/src/pages/app-store.astro +++ b/src/pages/app-store.astro @@ -17,7 +17,7 @@ const canonicalUrl = 'https://pilotprotocol.network/app-store'; const featured = featuredApps(); const hero = featured[0]; const sideFeatured = featured.slice(1, 4); -const freshPinned = ['io.pilot.agentphone', 'io.pilot.orthogonal', 'io.pilot.bowmark', 'io.pilot.miren', 'io.pilot.smol', 'io.pilot.wallet', 'io.pilot.slipstream']; +const freshPinned = ['io.pilot.didit', 'io.pilot.agentphone', 'io.pilot.orthogonal', 'io.pilot.bowmark', 'io.pilot.miren', 'io.pilot.smol', 'io.pilot.wallet', 'io.pilot.slipstream']; const freshExclude = new Set(['io.pilot.postgres', 'io.pilot.docker']); const fresh = [ ...freshPinned.map((id) => apps.find((a) => a.id === id)).filter(Boolean), From 63cccdadd8c0d3d36daefd2f3d5621a3333fe5c0 Mon Sep 17 00:00:00 2001 From: pilot-plain-bot <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 00:17:25 +0000 Subject: [PATCH 4/4] chore(plain): auto-regenerate stale machine-UI twins --- src/pages/plain/app-store.astro | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/pages/plain/app-store.astro b/src/pages/plain/app-store.astro index 96d78a5..934b329 100644 --- a/src/pages/plain/app-store.astro +++ b/src/pages/plain/app-store.astro @@ -1,27 +1,26 @@ --- // Auto-generated by scripts/regen-plain.mjs. Edit the marketing source and re-run. // plain-source: src/pages/app-store.astro -// plain-source-sha256: 8a9d28e8652fe841199f155c1275837551d175fa50db613f725f9fedecb7c93c +// plain-source-sha256: 3ee1de7d24a2e16e41b490f914ad2a359b7031d57cb2721fa82ec79674b5d493 import PlainLayout from '../../layouts/PlainLayout.astro'; ---

App Store

-

The Pilot Protocol App Store provides agent apps. Apps install as sha256-pinned, signature-verified native services. They are auto-spawned by the daemon and callable over typed IPC.

+

A collection of agent apps for the Pilot Protocol. Apps install as sha256-pinned, signature-verified native services, are auto-spawned by the daemon, and are callable over typed IPC.

-

App Discovery

-

The App Store contains curated lists, including featured apps and new or updated apps. Apps are also organized by category. A search function is available to find apps by name, capability, or vendor.

+

Browsing Apps

+

The App Store highlights featured, new, and recently updated apps. Apps are organized into categories and can be found with search.

Publishing an App

-

Apps are published by signing a manifest.json file, attaching a bundle, and opening a pull request.

-

Once merged, the app is installable on the overlay network with the pilotctl command.

+

To publish an app, sign a manifest.json, attach a bundle, and open one pull request. Once merged, the app becomes installable on the overlay network via its ID.

pilotctl appstore install <id>

Related