Parity ledger — route → status·
Generated from ~/tinyai-id @ 72244113 and worker submodule @ fffcf20.
Status values: todo · ported (code compiles in template) · tested (source tests pass in template) · n/a (deliberately excluded, reason given).
Parity: 64 / 64 web routes ported (32 with source tests green) · 121 / 121 worker endpoints ported (+ oauth.ts unmounted — DRIFT #11) · 100%
R2 skeleton (not counted): GET /api/health (web, edge) and GET /health (worker) exist only to prove the monorepo builds; neither is a source route.
apps/web — app/api/* (64 route files)·
| Route | Methods | Source lines | Source tests | Status |
|---|---|---|---|---|
/api/account-voice |
GET,POST | 66 | account-voice-write.test.ts | tested (account-voice-write) |
/api/archives |
GET,POST,DELETE | 85 | — | ported (session-archive lib tested) |
/api/auth/cli |
POST | 64 | cli-token.test.ts | tested (cli-token) |
/api/auth/cli/token |
POST | 53 | cli-token.test.ts | tested (cli-token) |
/api/auth |
GET | 138 | oauth-csrf.test.ts | tested (auth, oauth-csrf) |
/api/auth/webauthn/login |
GET,POST | 122 | webauthn-login.test.ts | tested (webauthn-login) |
/api/auth/webauthn/register |
GET,POST | 130 | — | ported (no source unit test; verification logic verbatim) |
/api/chain/join |
GET | 80 | chain-join-doc.test.ts chain-join.test.ts | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
/api/chain/status |
GET | 62 | chain-status.test.ts | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
/api/chat |
POST | 2106 | chat-route.test.ts flipper-tools.test.ts limit-message.test.ts nicla-tools.test.ts nicla-voice-tools.test.ts page-code-trust.test.ts prompt.test.ts spawn-tree-states.test.ts wearables-android.test.ts wearables-ios.test.ts | tested (chat-route; page-code-trust wiring its now active) |
/api/chat/tool-result |
POST | 50 | — | ported |
/api/control |
POST | 146 | control-limit-order.test.ts limit-message.test.ts write-routes.test.ts | tested (write-routes, control-limit-order) |
/api/delete |
DELETE | 47 | write-routes.test.ts | tested (write-routes) |
/api/devices/adopt |
POST | 68 | adopt-route.test.ts ios-adopt-failure.test.ts nicla-android-parity.test.ts | ported |
/api/devices/ask |
POST | 102 | device-ask-route.test.ts device-ask-universe.test.ts | tested (device-ask-universe) |
/api/devices/endpoint/chat |
POST | 77 | endpoint-chat-route.test.ts | ported |
/api/devices/endpoint |
GET | 123 | devices-camera-panel.test.ts | ported |
/api/devices/event |
POST | 53 | nicla-android-parity.test.ts | ported |
/api/devices/heartbeat |
POST | 63 | devices-route.test.ts | ported |
/api/devices/messages |
POST | 50 | — | ported |
/api/devices/relay |
POST,GET,PUT,PATCH | 149 | relay-poll-verdict.test.ts relay-route.test.ts relay-send.test.ts | ported |
/api/devices |
GET,POST,DELETE | 151 | devices-route.test.ts enroll-outcome.test.ts revoke-message.test.ts | ported |
/api/devices/task-result |
POST | 55 | — | ported |
/api/devices/transcript |
POST,GET | 113 | android-transcripts-readback.test.ts transcript-route.test.ts | ported |
/api/erc8004/registration/[slug] |
GET | 203 | erc8004-registration.test.ts x402-facilitator.test.ts x402-network-parity.test.ts x402-tiny-network.test.ts | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
/api/events |
GET | 51 | — | ported |
/api/firmware/manifest |
POST,GET,PUT | 146 | firmware-channel.test.ts | tested (firmware-channel) |
/api/follow |
GET,POST | 63 | — | ported |
/api/graph |
GET,POST | 113 | graph-query.test.ts memory-list.test.ts | ported |
/api/job-run |
POST | 246 | flipper-ble.test.ts flipper-tools.test.ts job-run.test.ts nicla-tools.test.ts nicla-voice-tools.test.ts | tested (job-run) |
/api/jobs |
GET,POST,DELETE | 101 | write-routes.test.ts | tested (write-routes) |
/api/learnings |
GET,POST,DELETE | 143 | learnings-delete-scope.test.ts memory-list.test.ts unlearn-scope.test.ts | tested (memory-list, learnings-delete-scope, unlearn-scope — 13 census its skip until MemoryPanel/tools/memory/messages/voice land) |
/api/location |
GET,POST,DELETE | 97 | — | ported (worker SQL tested: locations-sql) |
/api/login |
POST | 81 | — | ported (rate-limit tested; login route test lands with tiny CRUD in R5) |
/api/logout |
POST,GET | 16 | — | ported (no source unit test; 16 lines verbatim) |
/api/manifest/[slug] |
GET | 64 | — | ported (tiny-record tested) |
/api/me |
GET | 49 | standing.test.ts | ported (free-tier tested; standing test waits for rate-limit.ts in the next slice) |
/api/media |
POST | 67 | media-route.test.ts | ported |
/api/messages |
GET,POST,DELETE | 131 | dm-length-parity.test.ts ios-messages-load-reason.test.ts load-failure-caption.test.ts memory-list.test.ts | ported |
/api/model-config |
GET,POST | 74 | — | tested (settings-routes) |
/api/model-providers |
GET,POST,DELETE | 107 | — | tested (settings-routes) |
/api/prefs |
GET,POST | 57 | — | tested (settings-routes) |
/api/push |
GET,POST,DELETE | 85 | — | ported |
/api/run-tool |
POST | 44 | — | tested (user-tools via lib) |
/api/share |
POST,GET,DELETE | 164 | share-route.test.ts write-routes.test.ts | tested (share-route, write-routes) |
/api/telegram |
GET,POST,DELETE | 77 | — | tested (worker telegram-poll + telegram-authz) |
/api/tiny |
POST | 132 | tiny-read-degrade.test.ts | ported (no source unit test; worker get tested via tiny-read-degrade later) |
/api/tools/install |
POST | 161 | — | ported |
/api/tools |
GET,POST,DELETE | 108 | — | tested (user-tools via lib) |
/api/tools/run |
POST | 71 | — | ported |
/api/tools/trust |
GET,POST,DELETE | 97 | write-routes.test.ts | tested (write-routes) |
/api/udid |
GET,POST | 169 | udid-route.test.ts | tested (udid-route, 16; owner default inverted — DRIFT #10) |
/api/visit |
POST | 68 | limit-cost-routes.test.ts | ported (limit-cost-routes waits for /api/worker) |
/api/voice/recording-status/[id] |
GET | 70 | voice-playback-refusal.test.ts voice-recording-status-route.test.ts | tested (voice-recording-status-route) |
/api/voice/replay/[id] |
GET | 42 | — | ported |
/api/voice/session |
POST | 142 | flipper-ble.test.ts | ported |
/api/voice/sessions |
GET | 25 | call-recordings-load.test.ts | ported |
/api/voice/tool |
POST | 122 | flipper-ble.test.ts flipper-tools.test.ts graph-query.test.ts nicla-tools.test.ts nicla-voice-tools.test.ts unlearn-scope.test.ts | ported (voice-tools) |
/api/wallet/faucet |
POST | 164 | dev-keys.test.ts faucet-mint-not-a-deposit.test.ts faucet-no-answer.test.ts pay-deadline-above-route.test.ts x402-pay-route.test.ts | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
/api/wallet |
GET,POST | 168 | — | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
/api/wallet/withdraw |
POST | 318 | deadlines.test.ts dev-keys.test.ts pay-deadline-above-route.test.ts withdraw-settle-network.test.ts x402-pay-route.test.ts x402-settle-unknown.test.ts | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
/api/worker |
POST | 74 | limit-cost-routes.test.ts | tested (limit-cost-routes) |
/api/x402/chat/[slug] |
POST,GET | 697 | x402-credit-counterparty.test.ts x402-durability.test.ts x402-facilitator.test.ts x402-network-parity.test.ts x402-settle-unknown-record.test.ts x402-settle-unknown.test.ts x402-tiny-network.test.ts | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
/api/x402/pay |
POST,PUT | 880 | pay-deadline-above-route.test.ts x402-pay-route.test.ts x402-payer.test.ts x402-settle-unknown.test.ts x402-spend-reconcile.test.ts x402-spend-reverse-sent.test.ts | tested (gated PAYMENTS_ENABLED; source suites green, DRIFT #28) |
apps/worker — router endpoints (chatgpt-plugin-tinyai/src/index.ts)·
| Method | Path | Handler | Source module | Status |
|---|---|---|---|---|
| POST | /upsert |
UpsertCall | upsert.ts | ported (upsert-merge tested) |
| DELETE | /tiny |
TinyDeleteCall | delete.ts | ported (delete-cascade test waits for retrieve.ts) |
| GET | /get |
GetCall | get.ts | ported |
| GET | /retrieve |
RetrieveCall | retrieve.ts | ported (tiny-delete-cascade tested) |
| POST | /turns |
TurnStoreCall | turns.ts | tested (turns-memory) |
| GET | /list |
ListCall | list.ts | ported |
| GET | /legal |
LegalCall | legal.ts | tested (worker legal.test — brand from APP_URL, placeholder text) |
| GET | /community |
CommunityCall | community.ts | ported |
| GET | /profile |
ProfileCall | profile.ts | ported |
| POST | /share |
ShareCreateCall | share.ts | ported |
| GET | /share |
ShareGetCall | share.ts | ported |
| DELETE | /share |
ShareDeleteCall | share.ts | ported |
| GET | /share/list |
ShareListCall | share.ts | ported |
| POST | /archive |
ArchiveCreateCall | archives.ts | ported |
| GET | /archive/list |
ArchiveListCall | archives.ts | ported |
| GET | /archive |
ArchiveGetCall | archives.ts | ported |
| DELETE | /archive |
ArchiveDeleteCall | archives.ts | ported |
| GET | /learnings |
LearningsListCall | learnings.ts | ported |
| POST | /learnings |
LearningsAddCall | learnings.ts | ported |
| DELETE | /learnings |
LearningsDeleteCall | learnings.ts | ported |
| GET | /graph/neighbors |
GraphNeighborsCall | learnings.ts | ported (memory-graph tested) |
| GET | /graph/all |
GraphAllCall | learnings.ts | ported (memory-graph tested) |
| GET | /graph/conflicts |
GraphConflictsCall | learnings.ts | ported (memory-graph tested) |
| POST | /graph/resolve |
GraphResolveCall | learnings.ts | ported (memory-graph tested) |
| POST | /graph/social |
SocialRecordCall | learnings.ts | ported |
| GET | /graph/social |
SocialGraphCall | learnings.ts | ported |
| POST | /follow |
FollowCall | learnings.ts | ported |
| GET | /graph/feed |
FeedCall | learnings.ts | ported |
| GET | /reputation |
ReputationGetCall | reputation.ts | ported (reputation test waits for withdrawals.ts, R7) |
| POST | /events |
EventsEmitCall | events.ts | ported |
| GET | /events |
EventsListCall | events.ts | ported |
| POST | /jobs |
JobsCreateCall | scheduler.ts | tested (scheduler, scheduler-cas, scheduler-ownership, job-cadence, job-abandoned, worker scheduler-callback) |
| GET | /jobs |
JobsListCall | scheduler.ts | tested (scheduler, scheduler-cas, scheduler-ownership, job-cadence, job-abandoned, worker scheduler-callback) |
| DELETE | /jobs |
JobsDeleteCall | scheduler.ts | tested (scheduler, scheduler-cas, scheduler-ownership, job-cadence, job-abandoned, worker scheduler-callback) |
| GET | /push/key |
PushKeyCall | push.ts | ported (push-crypto tested) |
| POST | /push/subscribe |
PushSubscribeCall | push.ts | ported |
| DELETE | /push/subscribe |
PushUnsubscribeCall | push.ts | ported |
| POST | /push/send |
PushSendCall | push.ts | ported (push-crypto, relay-notify tested) |
| GET | /tools/browse |
ToolsBrowseCall | tools.ts | tested (worker tools-marketplace) |
| GET | /tools |
ToolsListCall | tools.ts | tested (worker tools-marketplace) |
| POST | /tools |
ToolsUpsertCall | tools.ts | tested (worker tools-marketplace) |
| DELETE | /tools |
ToolsDeleteCall | tools.ts | tested (worker tools-marketplace) |
| POST | /telegram/api |
TelegramApiCall | telegram-api.ts | ported |
| POST | /telegram |
TelegramConfigCall | telegram.ts | ported |
| GET | /telegram |
TelegramGetCall | telegram.ts | ported |
| DELETE | /telegram |
TelegramDeleteCall | telegram.ts | ported |
| GET | /prefs |
PrefsGetCall | prefs.ts | ported |
| POST | /prefs |
PrefsSetCall | prefs.ts | ported |
| GET | /model-config |
ModelConfigGetCall | model-config.ts | tested (worker model-keys) |
| POST | /model-config |
ModelConfigSetCall | model-config.ts | tested (worker model-keys) |
| GET | /model-providers |
ModelProvidersGetCall | model-providers.ts | tested (worker model-keys) |
| POST | /model-providers |
ModelProvidersSetCall | model-providers.ts | tested (worker model-keys) |
| DELETE | /model-providers |
ModelProvidersDeleteCall | model-providers.ts | tested (worker model-keys) |
| GET | /account-voice |
AccountVoiceGetCall | account-voice.ts | tested (account-voice-write) |
| POST | /account-voice |
AccountVoiceSetCall | account-voice.ts | tested (account-voice-write) |
| POST | /device/enroll |
DeviceEnrollCall | devices.ts | tested (16 source test files) |
| POST | /device/heartbeat |
DeviceHeartbeatCall | devices.ts | tested (16 source test files) |
| GET | /device/list |
DevicesListCall | devices.ts | tested (16 source test files) |
| DELETE | /device |
DeviceRevokeCall | devices.ts | tested (16 source test files) |
| POST | /device/rotate-token |
DeviceRotateTokenCall | devices.ts | tested (16 source test files) |
| POST | /device/event |
DeviceEventCall | devices.ts | tested (16 source test files) |
| POST | /device/ask |
DeviceAskCall | ask.ts | tested (16 source test files) |
| POST | /device/endpoint/call |
DeviceEndpointCallRoute | devices.ts | tested (16 source test files) |
| POST | /firmware/publish |
FirmwarePublishCall | firmware.ts | tested |
| GET | /firmware/current |
FirmwareCurrentCall | firmware.ts | tested |
| POST | /firmware/device-current |
FirmwareDeviceCurrentCall | firmware.ts | tested |
| POST | /transcript |
TranscriptAddCall | transcripts.ts | tested (transcripts-sql) |
| GET | /transcript/list |
TranscriptListCall | transcripts.ts | tested (transcripts-sql) |
| GET | /transcript |
TranscriptGetCall | transcripts.ts | tested (transcripts-sql) |
| POST | /location/heartbeat |
LocationBeatCall | locations.ts | tested (locations-sql) |
| GET | /location/list |
LocationsListCall | locations.ts | tested (locations-sql) |
| DELETE | /location |
LocationDeleteCall | locations.ts | tested (locations-sql) |
| POST | /device/relay/send |
RelaySendCall | relay.ts | tested (16 source test files) |
| POST | /device/relay/poll |
RelayPollCall | relay.ts | tested (16 source test files) |
| POST | /device/relay/reply |
RelayReplyCall | relay.ts | tested (16 source test files) |
| GET | /device/relay/recv |
RelayRecvCall | relay.ts | tested (16 source test files) |
| POST | /device/relay/deposit |
RelayDepositCall | relay.ts | tested (16 source test files) |
| POST | /device/task-result |
RelayTaskResultCall | relay.ts | tested (16 source test files) |
| GET | /pay/balance |
PayBalanceCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/invoke |
PayInvokeCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/transfer |
PayTransferCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/refund |
PayRefundCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/price |
PayPriceSetCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| GET | /pay/pricing |
PayPricingCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/credit |
PayCreditCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/spend |
PaySpendCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/spend-sent |
PaySpendSentCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/spend-reverse |
PaySpendReverseCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/settle-unknown |
PaySettleUnknownCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| GET | /pay/reconcile-status |
PayReconcileStatusCall | payments.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/link-address |
PayLinkAddressCall | deposits.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/claim |
PayClaimCall | deposits.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| GET | /pay/deposit-info |
PayDepositInfoCall | deposits.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/faucet |
PayFaucetCall | deposits.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/withdraw-request |
WithdrawRequestCall | withdrawals.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/withdraw-complete |
WithdrawCompleteCall | withdrawals.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| POST | /pay/withdraw-fail |
WithdrawFailCall | withdrawals.ts | tested (gated PAYMENTS_ENABLED; 12 source suites + payments-gate) |
| GET | /ring |
RingGetCall | ring.ts | ported |
| POST | /ring |
RingAddCall | ring.ts | ported |
| POST | /visit |
VisitCall | visit.ts | ported |
| POST | /media/upload |
MediaUploadCall | media.ts | tested (16 source test files) |
| GET | /media/:key |
MediaGetCall | media.ts | tested (16 source test files) |
| POST | /device/tool-result |
ToolResultPostCall | media.ts | tested (16 source test files) |
| GET | /device/tool-result |
ToolResultGetCall | media.ts | tested (16 source test files) |
| POST | /voice/session |
(inline → voice.ts) | voice.ts | tested (voice-recording-range/gaps, voice-teardown-monotonic, media-retention-manifest) |
| GET | /voice/connect/:id |
(inline → voice.ts) | voice.ts | tested (voice-recording-range/gaps, voice-teardown-monotonic, media-retention-manifest) |
| POST | /voice/reap/:id |
(inline → voice.ts) | voice.ts | tested (voice-recording-range/gaps, voice-teardown-monotonic, media-retention-manifest) |
| GET | /voice/recording/:id |
(inline → voice.ts) | voice.ts | tested (voice-recording-range/gaps, voice-teardown-monotonic, media-retention-manifest) |
| GET | /voice/sessions |
VoiceSessionsListCall | voice.ts | tested (voice-recording-range/gaps, voice-teardown-monotonic, media-retention-manifest) |
| GET | /voice/session |
VoiceSessionGetCall | voice.ts | tested (voice-recording-range/gaps, voice-teardown-monotonic, media-retention-manifest) |
| GET | /voice/replay/:id/:file |
(inline → voice.ts) | voice.ts | tested (voice-recording-range/gaps, voice-teardown-monotonic, media-retention-manifest) |
| POST | /message |
MessageSendCall | messages.ts | tested (16 source test files) |
| POST | /device/messages |
DeviceMessagesCall | messages.ts | tested (16 source test files) |
| GET | /messages |
MessagesListCall | messages.ts | tested (16 source test files) |
| GET | /message/unread |
MessagesUnreadCall | messages.ts | tested (16 source test files) |
| DELETE | /message |
MessageDeleteCall | messages.ts | tested (16 source test files) |
| POST | /user/upsert |
UserUpsertCall | users.ts | ported (users.ts verbatim; credential-binding tested) |
| GET | /user/get |
UserGetCall | users.ts | ported (users.ts verbatim; credential-binding tested) |
| POST | /credential/add |
CredentialAddCall | users.ts | ported (users.ts verbatim; credential-binding tested) |
| GET | /credential/list |
CredentialListCall | users.ts | ported (users.ts verbatim; credential-binding tested) |
| POST | /credential/signcount |
CredentialSignCountCall | users.ts | ported (users.ts verbatim; credential-binding tested) |
apps/worker — non-HTTP entry points·
| Entry | What | Status |
|---|---|---|
scheduled (cron * * * * *) |
runDueJobs, pollTelegramBots, sweepToolUpdates, LOCATION_SWEEP_SQL, reconcileSentSpends, reconcileSettleUnknown, sweepReconcileAlarm | ported — runDueJobs, LOCATION_SWEEP, pollTelegramBots, sweepToolUpdates + (PAYMENTS_ENABLED) reconcileSentSpends, reconcileSettleUnknown, sweepReconcileAlarm; was: partial — runDueJobs + location sweep + pollTelegramBots + sweepToolUpdates wired; payments reconciler lands with R8 |
email |
Email Routing: forwards <slug>@ to the tiny's customer email; hardcoded CF account id + owner fallback address → must become env |
tested — src/email.ts, EMAIL_OWNER_FORWARD / CLOUDFLARE_ACCOUNT_ID+TOKEN (DRIFT #30), 9 tests |
Durable Object VoiceSession |
live voice call relay (OpenAI Realtime ⇄ client), journals to R2 + D1 | ported (voice.ts verbatim; placeholder class removed; wrangler dry-run bundles) |
Skipped census tests (self-activating)·
Some source tests are cross-surface censuses: they read other files' source text.
Where the file is not ported yet, the it is it.skipIf(!has('<path>')) and turns
on by itself when the path appears. its that read ios/ or android/ are dropped —
this template has no mobile apps. Current skips: 23 (voice-teardown-monotonic 3 [mobile + app/calls page], memory-list 5, learnings-delete-scope 2, unlearn-scope 6, dm-send 1, graph-query 1, page-code-trust 5, relay-send 3 (censused by it.skipIf; see npx vitest run --reporter=verbose | grep skipped for the live list), job-cadence 3) waiting on components/chat/MemoryPanel.tsx, components/chat/JobsPanel.tsx, lib/chat/slash-commands.ts, app/api/voice/tool/route.ts (R7/R9).
Chat runtime libs (R5)·
| lib | status |
|---|---|
| lib/bedrock-edge.ts, lib/chat/model.ts | ported verbatim; tests bedrock-eventstream, chat-helpers (additional-fields waits on components/chat/ModelSettings) |
| lib/chat/helpers.ts, events.ts, tool-filter.ts, page-code-trust.ts, graph-query.ts | ported verbatim; tests green (page-code-trust/graph-query wiring its skip until chat route, Chat.tsx, strands-events, voice/tool land) |
| lib/chat/relay-send.ts, dm-send.ts, dm-attachments.ts | ported; MEDIA_ORIGINS = TINY_WORKER_URL only (tinyai-id also pinned its production host); relay-send caller census skips until nicla/flipper/platform/devices-relay land |
| lib/chat/prompt.ts | ported; site host via APP_URL (siteHostName()); Android-app sentence dropped |
| lib/chat/tools/universe.ts, messages.ts, memory.ts, client-side.ts | ported; worker URL via lib/config (lazy WORKER()); tests universe-tools, dm-media-tools, dm-send, graph-query, unlearn-scope |
| lib/utils.ts (full), tools/http.ts | ported; parseOpenAPI default worker from TINY_WORKER_URL; tests utils, parse-openapi, http-tool |
| lib/chat/tools/platform.ts, spawn.ts, nicla.ts, nicla-voice.ts, flipper.ts | ported; WORKER = workerUrlOrPlaceholder() (module-scope, build-safe); run-tool proxy needs NEXT_PUBLIC_APP_URL; tests device-media, platform-tools, spawn-async, nicla-tools, use-device-endpoint (worker relay/devices census skips until R6) |
| lib/deadlines.ts, lib/x402/* (8 files: tiny-chain, facilitator, payer, top-up, wallet-client, explorer, faucet-countdown, use-faucet-countdown), lib/chain/* (5: rpc, status, join, calldata, explorer-core) | ported verbatim (env-only config: TINY_CHAIN_ID/RPC_URL/USDC_ADDRESS/EXPLORER_URL, PAYMENTS_NETWORK); tests top-up, chain-explorer, explorer, faucet-countdown, wallet-client, x402-quote-copy green (109); deadlines/chain-calldata/chain-identity/x402-facilitator/x402-payer/x402-tiny-network wait for the web money routes + chain/ + app/chain pages |
| app/api/chat/route.ts, app/api/chat/tool-result | ported; 44 worker URLs → ${WORKER}, prompt links → APP_URL/request origin, install_tool allowlist → TOOL_REPO_ALLOWLIST env; lib/x402/tiny-chain.ts (env-only) ported for paymentsNetwork |
Dependency layout note: the web app needs zod 4 + openai 6 (peer of @strands-agents/sdk) while the worker's
itty-router-openapi needs zod 3 + openai 4. Root devDependencies pin zod@4 / openai@6 so npm hoists those and
nests the worker's versions under apps/worker/node_modules — verified by a local wrangler dev smoke
(/health, /list, /community, /events, /push/key) after d1 migrations apply --local (all 34 apply clean).
| lib/voice/* (live, outcome, platform, playback, realtime, tools, tts, vad) + components/chat/voice.ts | ported verbatim; tests tts-chunk, vad, voice-platform, voice-tools green |
UI surface (R9)·
| slice | files | status |
|---|---|---|
| R9a shell | tailwind.config.js, postcss.config.js, app/globals.css, app/layout.tsx (+ lib/site.ts), components/{theme-provider,TinyLogo,SiteHeader,MapToggle,GlobalMapBackdrop,MapBackground,Analytics}.tsx, lib/{theme,map-pref,geo,relative-time,relative-tick,use-relative-tick}.ts, lib/chat/{whoami,session-expiry,auth-events}.ts, app/{loading,error,global-error}.tsx, app/{manifest,robots,sitemap}.ts, app/icon.png, public icons | ported; constants → env (DRIFT #31, #32); next build + next start verified (title/og/robots/sitemap/manifest from env, CSS 200); tests theme, geo, relative-*, session-expiry, auth-events (chat censuses self-activate) |
| R9b chat surface | components/chat/* (Chat.tsx closure: 73 files incl. lib/chat client libs, lib/{community,file-attachments,model-pricing,model-registry,sse,webllm}, lib/public-config.ts), app/page.tsx (real home + A2HS QR), app/not-found.tsx | ported verbatim; 8 browser-side worker/host constants → env (DRIFT #33); 69 upstream test files added (2849 pass / 10 skip); iOS/Android parity blocks dropped (render-ui-fallback, spawn-tree-states, tiny-read-degrade), R9c censuses self-activate (wallet/[slug]/Universe sinks); next build + headless Chrome render of / (desktop + 390px): onboarding, hero, composer, header, 0 page errors |
| R9c pages | app/[slug] (+loading), about, auth/cli, calls, chain (+ui, lookup, address/[addr], tx/[hash]), devices, map, og/[slug], universe (+loading, opengraph-image), vcard/[slug], voice, wallet, wearables (+handoff); components/{Community,FollowButton,Profile,ProfileToolCard,ProfileTools,UniverseDirectory}; lib/devices/revoke-message | ported verbatim (30 files); ~60 brand/origin/worker constants → env (DRIFT #34); 11 upstream test files added (native-client cases dropped, DRIFT #35); R9b's dormant censuses (wallet/[slug]/Universe sinks) now active: 189 files, 2936 pass / 5 skip; next build 24 static + all dynamic pages; next start curl of 15 routes 200 (vcard of an unknown tiny 404) with zero tiny.technology/@tinyaid/say.jpeg leakage; headless Chrome /about /universe /wallet /devices /chain /[slug]: 0 page errors |
R10 — fresh-deploy proof (in progress)·
| Step | Status |
|---|---|
Cloudflare storage under tiny-vercel-* via scripts/bootstrap-cloudflare.mjs |
DONE 2026-09-15 08:21Z — 3 KV, D1, 2 Vectorize (+2 metadata indexes), R2; idempotent re-run reuses all 7; ledger docs/PROVISIONED.md |
| D1 schema | DONE — all 36 migrations applied remotely (39 tables) |
| Worker deployed | DONE — https://tiny-vercel-worker.cagatay.workers.dev (version ee095c84); smoke: /health ok, /get not-exists sentinel, /community empty, /pay/* 404 payments-disabled JSON, /upsert schema-validates |
| Scratch Vercel project (D-004) | DONE 2026-09-15 08:33Z — tiny-vercel-scratch (team cagataycali-s-team, rootDirectory apps/web, 10 production env vars, deployed from the CLI in 2m). https://tiny-vercel-scratch.vercel.app: all pages 200, /api/health workerConfigured+appUrlConfigured, /api/events 401, payments 404-off, unknown slug renders "Create an AI named …" exactly like production, anonymous /api/chat streams a full SSE agent turn through the fresh worker (pong, 14 events, [DONE]). Worker APP_URL re-pointed at the scratch origin and redeployed (version a9cee71b) |
| GitHub OAuth App (sign-in path) | BLOCKED on owner — D-010; anonymous surface proven, authenticated surface (create tiny, passkey, devices, memory) waits for the OAuth app |
| docs/DEPLOY.md walkthrough, README Deploy button, docs/VERCEL_TEMPLATE.md checklist | DONE 2026-09-15 09:02Z — README button (root-directory=apps/web, 10 env keys, envLink→DEPLOY.md, demo card), apps/web/vercel.json (monorepo install/build + maxDuration 300 for /api/chat) proven by a fresh CLI production deploy (f37eoobja, ready in 1m, cd ../.. && npm ci 926 pkgs), VERCEL_TEMPLATE.md against the live submit form + deploy-button docs (charter URL 404s, noted) |
| Sample endpoint device (charter rule 8) | DONE 2026-09-15 09:40Z — examples/echo-device (zero-dep server.mjs + enroll.mjs + 7 node:test cases, in root npm test). PROVEN live against the scratch deployment through a Cloudflare quick tunnel: enroll → device 6d5d1ded listed as endpoint with url; /api/devices/endpoint telemetry 200 + snapshot 200 image/png 89B; /api/devices/endpoint/chat 200; and a real /api/chat agent turn used use_device and answered with the device's actual uptime + Node version. Session for the proof was an operator-minted CLI-shaped JWT (own AUTH_JWT_SECRET) since GitHub OAuth is D-010; the browser consent path in enroll.mjs is untested until then |
| Teardown rehearsal | DONE 2026-09-15 10:35Z — run TWICE: teardown 9s (exactly the 8 prefixed rows; 6 production KV ids and the Vercel project verified untouched by before/after listings), bootstrap+migrate 19s, secrets+deploy 14s = 33s to a serving worker at the same name-based URL; app needed no change. Fresh D1 proven (ids restart at 1), Vectorize recall after ~20s, full /api/chat turn recalled the new memory. Found+fixed: first run left the worker in the ledger although it was gone → teardown now re-lists on non-zero exit and logs every delete to .cloudflare-teardown.log. docs/DEPLOY.md “Rehearsed” section |
| R1–R9 re-verification on the REBUILT stack (charter rule 10) | DONE 2026-09-15 11:30Z — local: web 2936 passed/5 skipped, worker 122, echo-device 7, exit 0. Live against fresh D1/KV/Vectorize: R3 /api/me 401→200 with JWT, cli/token bad code 401, passkey login validation, logout; R5 chat turn (math) + tool use; R6 devices: echo device enrolled through a quick tunnel → telemetry 200, snapshot image/png, agent use_device ×3 answered real uptime, events/messages/jobs/push 200, revoke ok; R7 user row via /user/upsert (what the OAuth callback does — D-010 still means no browser sign-in) → create tiny via /api/control → /api/me lists it, public config read active:true, chat honours its system prompt ("REHEARSAL Hi there!"), /community lists owner+tiny, /retrieve (Vectorize) finds it with scratch-app URLs, share create/read/revoke, graph social, archives, voice sessions, /api/delete → active:false; R8 every payments route answers the 404 "payments disabled" hint; R9 /, /devices, /<tiny>, /tiny?share= 200. One inherited footgun found → D-011. |
cli — apps/cli (npx tiny-vercel, ported from tiny-tech@0.13.7 @ b8b9397)·
Inventory: docs/CLI.md. Rungs per the charter's CLI addition; status values as above plus proven (exercised against the live scratch deployment).
| Rung | Scope | Status |
|---|---|---|
| C1 inventory | commands, 72 modules / 28,579 lines, 54 tiny.technology refs with file:line, 72 env vars, 61 test files, web-vs-worker reach (27 web routes all present; 3 public worker reads + 1 media allowlist) |
DONE 2026-09-15 18:05Z — docs/CLI.md; DRIFT #36 (/api/wallet/balance) |
| C2 skeleton + verbatim port | apps/cli in the repo, tsc build, 61 test suites green, root CI runs it |
DONE 2026-09-15 18:05Z — 152 files copied verbatim (src, test, menubar, tsconfig); tsc clean in 2.3s; node --test 1432/1432 pass in 17s; root npm test/typecheck call it via --prefix apps/cli; CI installs both lockfiles. NOT a hoisted workspace member: the web app pins React 18.2.0 and Ink 7 needs React ≥19 — hoisting put Ink next to React 18 and import('ink') failed at runtime (useEffectEvent missing), so the CLI keeps its own package-lock.json (D-012). gitleaks: 4 secret-shaped test fixtures (scrubber + OpenAPI auth tests) allowlisted by exact value/file |
| C3 one config | --api → TINY_API_URL → ~/.tiny/config.json → prompt; tiny-vercel init <url>; worker URL derived from <app>/api/health; 54 refs → 0; gitleaks clean |
DONE 2026-09-15 18:27Z — src/config.ts (resolution, init, /api/health probe, worker discovery + cache, ConfigRequiredError off-TTY), 12 new tests; apps/cli now has 0 tiny.technology refs in src/test/menubar/README (from 54+29+3+7); launchd label technology.tiny.daemon → dev.tiny-vercel.daemon; bin/prose tiny-tech → tiny-vercel; the ONE web change: /api/health adds siteName + workerUrl (public origin the browser bundle already ships; null when unset) + 3 tests; tray status gains webUrl so the menu bar opens the configured app; server tests run against a loopback fake deployment instead of the operator's prod worker. 1445/1445 CLI tests, Swift suite green, gitleaks clean |
| C4 live proof | init https://tiny-vercel-scratch.vercel.app → CLI-token login (operator JWT, D-010) → enroll this Mac → heartbeat on /devices → use_device round-trip from the scratch web agent answering a real shell question; recorded in docs/EVIDENCE.md |
DONE 2026-09-15 18:42Z — scratch redeployed with the health change; init derived the worker; login ran the REAL loopback + code-exchange path (the consent click reproduced with an operator session because D-010 leaves no browser sign-in) → credentials.json + device.json; daemon heartbeat → /api/devices shows online:true with 18 capabilities; web agent use_device invoke → this Mac ran cat /tmp/tv-proof-335ad3a4.txt && uname -m && sw_vers -productVersion → tiny-vercel-proof-335ad3a4 / arm64 / 26.4.1 came back in the chat (22 s). Device revoked, temp home + JWT deleted. docs/EVIDENCE.md |
| C5 packaging | npm pack listing, npm publish --dry-run, startup time + size in docs/EVIDENCE.md; owner asked ONCE about publishing tiny-vercel@0.1.0 |
DONE 2026-09-15 18:50Z — tarball 425.5 kB / 1.4 MB / 75 files (dist + package.json + README), gitleaks clean, 0 brand refs; fresh install 3.1 s → working tiny-vercel bin; help 0.08 s, init 0.21 s, MCP initialize 744 ms. npm publish --dry-run OK; name free (404). Owner asked once via dialog (240 s) — no answer → publish DEFERRED (D-013). Also: this Mac has no npm login (E401), so publishing needs the owner's npm login anyway |
| C6 docs | README + docs-site page "CLI: npx tiny-vercel"; this section at 100% | DONE 2026-09-15 19:05Z — README § "CLI — npx tiny-vercel" + apps/cli row in Shape + Devices table repointed; docs site start/cli.md (nav under Get started, card on the start page), ledgers CLI.md + EVIDENCE.md linked from Reference; every user-facing npx tiny-tech in README/docs → npx tiny-vercel; mkdocs build --strict clean |
cli parity: 13 / 13 commands ported · 61 / 61 source test files green (+ config.test.mjs) · 54 / 54 constants removed · 100%
Commands (13)·
| Command | Source | Status |
|---|---|---|
login / logout / whoami / devices |
cli.ts, auth.ts, api.ts | proven live (EVIDENCE § C4 steps 3–4); auth/api/device suites tested |
init <url> (NEW — the one config) |
config.ts | proven live (step 1); 12 tests |
connect [app] / onboard [status] / sync |
integrations.ts, onboard.ts, tui/onboard-app.tsx | tested (integrations, integrations-store, onboard suites); login printed the onboard hint live |
serve (MCP stdio) |
server.ts | tested (server, server-device suites against a loopback deployment; initialize 744 ms measured) |
tui / repl / one-shot / (none) |
agent/, tui/ | tested (agent, tui, conversations, layout, components, voice-call, realtime, speech, human-type, markdown suites); interactive TUI not driven in this lane |
daemon install\|show\|status\|logs\|restart\|uninstall |
daemon.ts | tested (daemon suite: unit/plist rendering with the new label); not installed on the proof machine (it already runs the owner's production daemon) |
mesh [peers\|send\|broadcast] (enroll + heartbeat + relay) |
mesh/*, device.ts | proven live (steps 5–7: heartbeat online, use_device round-trip); mesh, mesh-registry, relay-poller, device suites tested |
tray <action> + menubar/ Swift client |
tray.ts, menubar/ | proven live (step 8: tray status + webUrl on the socket); tray, tray-notify suites + swift test green |