@zackbart/connecta 0.35.0 → 0.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +8 -4
  3. package/bin/version.mjs +1 -1
  4. package/dist/auth/downstream-oauth.js +71 -79
  5. package/dist/auth/static-oauth.js +104 -26
  6. package/dist/connectors/api-connector.d.ts +17 -0
  7. package/dist/connectors/api-connector.js +3 -1
  8. package/dist/http/client.js +1 -1
  9. package/dist/http/hatch-paging.js +2 -2
  10. package/dist/http/paging.js +3 -89
  11. package/dist/http/provider.js +1 -2
  12. package/dist/http/services.js +1 -1
  13. package/dist/http/tools.js +1 -27
  14. package/dist/operator-ui/contract.d.ts +1 -0
  15. package/dist/operator-ui/generated.js +4 -4
  16. package/dist/program-writes.js +0 -1
  17. package/dist/providers/_shared/google/kit.js +29 -139
  18. package/dist/providers/_shared/rest/kit.js +4 -404
  19. package/dist/providers/_shared/sensitive-fields.js +0 -16
  20. package/dist/providers/breeze/api.js +2 -2
  21. package/dist/providers/ccb/api.js +1 -1
  22. package/dist/providers/cloudflare/api.js +8 -8
  23. package/dist/providers/cloudflare/lib/config.d.ts +2 -1
  24. package/dist/providers/docs/api.js +1 -1
  25. package/dist/providers/docs/tools.js +1 -2
  26. package/dist/providers/drive/api.js +2 -2
  27. package/dist/providers/drive/lib/hatch.js +1 -1
  28. package/dist/providers/drive/tools.js +1 -1
  29. package/dist/providers/forms/api.js +1 -1
  30. package/dist/providers/forms/lib/hatch.js +1 -1
  31. package/dist/providers/forms/tools.js +2 -3
  32. package/dist/providers/github/api.js +1 -1
  33. package/dist/providers/github/lib/discovery.js +2 -2
  34. package/dist/providers/gmail/api.js +1 -1
  35. package/dist/providers/gmail/tools.js +2 -2
  36. package/dist/providers/granola/api.js +155 -0
  37. package/dist/providers/granola/index.d.ts +10 -0
  38. package/dist/providers/granola/index.js +68 -0
  39. package/dist/providers/granola/openapi.generated.js +30 -0
  40. package/dist/providers/granola/safety.js +37 -0
  41. package/dist/providers/granola/skill.generated.js +5 -0
  42. package/dist/providers/granola/tools.js +2 -0
  43. package/dist/providers/overflow/api.js +26 -26
  44. package/dist/providers/planning-center/api.js +4 -4
  45. package/dist/providers/planning-center/lib/constants.d.ts +1 -1
  46. package/dist/providers/planning-center/lib/json-api.js +2 -2
  47. package/dist/providers/quickbooks/api.js +299 -0
  48. package/dist/providers/quickbooks/index.d.ts +13 -0
  49. package/dist/providers/quickbooks/index.js +93 -0
  50. package/dist/providers/quickbooks/lib/query.js +118 -0
  51. package/dist/providers/quickbooks/lib/writes.js +168 -0
  52. package/dist/providers/quickbooks/safety.js +222 -0
  53. package/dist/providers/quickbooks/skill.generated.js +5 -0
  54. package/dist/providers/quickbooks/tools.js +117 -0
  55. package/dist/providers/sheets/api.js +1 -1
  56. package/dist/providers/sheets/lib/hatch.js +2 -2
  57. package/dist/providers/sheets/lib/requests.js +1 -1
  58. package/dist/providers/sheets/tools.js +1 -2
  59. package/dist/providers/slides/api.js +1 -1
  60. package/dist/providers/slides/tools.js +2 -2
  61. package/dist/providers/stripe/api.js +7 -7
  62. package/dist/providers/tithely/api.js +2 -2
  63. package/dist/providers/vercel/api.js +12 -12
  64. package/dist/providers/vercel/index.js +1 -2
  65. package/dist/providers/vercel/lib/pin.js +1 -1
  66. package/dist/routes/mcp.js +1 -1
  67. package/dist/routes/oauth.js +3 -0
  68. package/dist/runtime/admission.js +0 -12
  69. package/dist/runtime/call.js +0 -4
  70. package/dist/skills.js +0 -1
  71. package/dist/storage/keys.js +2 -3
  72. package/dist/types.d.ts +2 -0
  73. package/dist/ui.d.ts +1 -1
  74. package/dist/ui.js +0 -1
  75. package/dist/version.d.ts +1 -1
  76. package/dist/version.js +1 -1
  77. package/documentation/README.md +1 -0
  78. package/documentation/architecture.md +249 -366
  79. package/documentation/auth.md +56 -19
  80. package/documentation/code-mode.md +6 -6
  81. package/documentation/integrating.md +1 -1
  82. package/documentation/meta-tools.md +6 -3
  83. package/documentation/operator-tests.md +11 -2
  84. package/documentation/operator-ui.md +17 -5
  85. package/documentation/providers.md +492 -0
  86. package/package.json +12 -9
  87. package/templates/node/package.json +1 -1
  88. package/dist/operator-ui/agents.d.ts +0 -75
  89. package/dist/operator-ui/agents.js +0 -114
  90. package/dist/operator-ui/config-summary.js +0 -566
  91. package/dist/operator-ui/connection-map.js +0 -378
  92. package/dist/operator-ui/endpoints.js +0 -212
  93. package/dist/operator-ui/fix-prompts.d.ts +0 -18
  94. package/dist/operator-ui/fix-prompts.js +0 -79
  95. package/dist/operator-ui/health.js +0 -52
  96. package/dist/operator-ui/member-page.js +0 -97
  97. package/dist/operator-ui/overview.js +0 -126
  98. package/dist/operator-ui/setup-commands.js +0 -47
  99. package/dist/operator-ui/view.d.ts +0 -378
  100. package/dist/operator-ui/view.js +0 -631
  101. package/dist/providers/_shared/rest/dispatch.js +0 -21
  102. package/dist/providers/_shared/rest/tools.js +0 -592
@@ -426,7 +426,7 @@ client. A raw Worker stream established the runtime behavior; a custom auth
426
426
  provider returning a synthetic streaming 401 exercised Connecta's real admission
427
427
  wrapper. Each case had its own Connecta instance with one request permit and no
428
428
  queue. Health checks and subsequent MCP requests confirmed the same isolate ID.
429
- The [recorded observations](https://github.com/zackbart/connecta/blob/a0ac904513fac735582b4bc9c817a48300134328/scripts/probes/worker-disconnect-2026-09-25.json)
429
+ The [recorded observations](https://github.com/zackbart/connecta/blob/1ab92695f2636f904274d900ce209553358ff1f3/scripts/probes/worker-disconnect-2026-09-25.json)
430
430
  contain all twelve cases, including served flags and client-end timing.
431
431
 
432
432
  | Response and flag | Raw stream abort / cancel | Connecta source abort / cancel | Admission after response; next request |
@@ -486,23 +486,23 @@ MCP requests still rejected a competing request with 503 before the deadline;
486
486
  the first MCP request after the deadline returned all eight tools with 200 in
487
487
  the original isolate. Admission then reported zero active requests. Without the
488
488
  flag, the source still recorded no abort or cancellation, so recovery did not
489
- rely on runtime cleanup. The [recovery observations](https://github.com/zackbart/connecta/blob/32d8e94/scripts/probes/worker-disconnect-recovered-2026-09-25.json)
489
+ rely on runtime cleanup. The [recovery observations](https://github.com/zackbart/connecta/blob/1ab92695f2636f904274d900ce209553358ff1f3/scripts/probes/worker-disconnect-recovered-2026-09-25.json)
490
490
  also retain two inconclusive queue-handoff cases: concurrent client connections
491
491
  reached different isolates and could not establish an abandoned queued waiter.
492
- A [second trial using HTTP/2](https://github.com/zackbart/connecta/blob/b174812/scripts/probes/worker-disconnect-h2-2026-09-25.json)
492
+ A [second trial using HTTP/2](https://github.com/zackbart/connecta/blob/1ab92695f2636f904274d900ce209553358ff1f3/scripts/probes/worker-disconnect-h2-2026-09-25.json)
493
493
  repeated the twelve passing core cases and verified queued cancellation with
494
494
  request signals enabled. Even on one HTTP/2 connection, the no-signal queue case
495
495
  crossed isolates and remained inconclusive. The Node and workerd regression
496
496
  suites cover expired waiters, orphaned handoffs, and identity-safe late release
497
497
  deterministically.
498
498
 
499
- To repeat from a repository checkout, run
500
- `node scripts/probes/worker-disconnect.mjs` with an authenticated Wrangler.
501
- The script is not in the npm package. It deploys a disposable Worker containing
502
- only synthetic data, verifies the served configuration, saves observations under `eval/results/`,
503
- and deletes the Worker in `finally`. It uses no `waitUntil`, which would change
504
- the lifetime being measured. The production runtime build number was not
505
- exposed by the deployment; these findings are tied to the date and flags above.
499
+ The [historical probe source](https://github.com/zackbart/connecta/blob/1ab92695f2636f904274d900ce209553358ff1f3/scripts/probes/worker-disconnect.mjs)
500
+ and observations are retained in Git history, outside the current checkout and
501
+ npm package. The probe deployed a disposable Worker containing only synthetic
502
+ data, verified the served configuration, saved observations, and deleted the
503
+ Worker in `finally`. It used no `waitUntil`, which would change the lifetime
504
+ being measured. The production runtime build number was not exposed by the
505
+ deployment; these findings are tied to the date and flags above.
506
506
 
507
507
  ### Production Access bypass for agent endpoints
508
508
 
@@ -763,9 +763,9 @@ adoption, OAuth handoff ownership, single-use connect links, every downstream
763
763
  OAuth grant write and consent claim, the result stash, and initialization of the cursor signing key.
764
764
 
765
765
  Every key is built in `src/storage/keys.ts`, which lists each family with its
766
- scope, version, codec, and TTL policy; `test/storage-keys.node.test.ts` fails when
767
- two families overlap, another source file spells a prefix (constant concatenation
768
- folded), or a storage call passes a key holding literal text. Core hands
766
+ scope, version, codec, and TTL policy. Deployed-consumer persistence journeys
767
+ check actual owner isolation in the physical database; key probes retain NUL
768
+ refusal. Core hands
769
769
  subsystems namespaced views: `conn:<id>:` per connector, `principal:<key>:` per
770
770
  personal registry, `results:` and `subject:<key>:` for result paging.
771
771
 
@@ -1266,20 +1266,16 @@ removed. Legacy hosted selectors fail at construction with the generic migration
1266
1266
  path. GitHub retains its scope-enforced App identity and exposes a bounded repository-read and release-write hatch plus local scope discovery, scoped data search and guarded merge.
1267
1267
 
1268
1268
  [Decision 0011](https://github.com/zackbart/connecta/blob/main/decisions/0011-provider-standard.md)
1269
- records the provider standard now implemented by all 15 maintained providers. It fixes
1269
+ records the provider standard implemented by every maintained provider. It fixes
1270
1270
  one folder layout per kind and fixed evidence names. `drift.json` gets a
1271
1271
  generated block and the guide a generated Conventions section, and every
1272
- `api()` surface gets one agent-facing shape. Providers completed two migration
1273
- steps: onto the kit with unchanged output, then onto the standard surface.
1274
- Both `PENDING.step1` and `PENDING.step2` in `test/provider-standard.ts` are empty;
1275
- every maintained provider now meets the standard without a migration exemption.
1276
- `test/provider-standard.node.test.ts` holds every maintained provider folder to the
1277
- standard, and `test/provider-conventions.test.ts` checks the surface rules on
1278
- Node. `providers:generate` writes the standard's derived parts and
1279
- refuses a provider past step 1 that breaks the `drift.json` rules, or one past
1280
- step 2 that breaks the guide rules: `drift.json` version 2's `generated` block
1281
- (operations from the kit's `ProviderKitFacts` and evidence digests), and a guide's `## Conventions`, rendered
1282
- from the definition's declarations into `skill.generated.ts`.
1272
+ `api()` surface gets one agent-facing shape. Every maintained provider meets the
1273
+ standard without a migration exemption. `test/provider-standard.node.test.ts`
1274
+ holds every provider folder to it, and `test/provider-conventions.test.ts`
1275
+ checks the surface rules on Node. `providers:generate` refuses drift (D) and
1276
+ guide (G) violations before writing. It derives `drift.json` version 2's
1277
+ `generated` block from kit operations and evidence digests, and the guide's
1278
+ `## Conventions` from definition declarations into `skill.generated.ts`.
1283
1279
  The generator requires `fixtures.ts` to export `createAuthored()` with a
1284
1280
  nonempty offline `staticTools` catalog. Its input/output schemas derive one
1285
1281
  paging convention, including `get_*`, hatch search and details, excluding
@@ -1291,8 +1287,9 @@ reports a nonzero explicit refusal count with singular/plural wording and
1291
1287
  points to the actual prefixed details tool with method/path lookup; it never
1292
1288
  embeds the refusal table. Unreviewed operations remain refused.
1293
1289
  `ProviderContext.usageGuide` selects a guide's `<!-- when: <key> -->` blocks
1294
- with the definition's `blocks`. `providers:check` reads both record versions,
1295
- reports a manifest operation no endpoint row records at the provider's level,
1290
+ with the definition's `blocks`. Maintained drift records use version 2;
1291
+ `providers:check` retains version-1 endpoint/manual record parsing for historical
1292
+ reports, while OpenAPI generation and checks use `evidence/openapi.json`. It reports a manifest operation no endpoint row records at the provider's level,
1296
1293
  and lists manual checks last verified more than 180 days ago. Its offline
1297
1294
  record validator, `scripts/drift-validate.mjs`, also gates `providers:generate`
1298
1295
  and the standard suite, so a record they accept is one `providers:check` reads.
@@ -1324,14 +1321,15 @@ A composition moves only by explicit review of its source pins/documents;
1324
1321
  `--record` and `--file` cannot replace it. `providers:check` compares the actual
1325
1322
  public documents independently; it never fetches a synthetic combined URL.
1326
1323
 
1327
- The generic REST connector (`src/providers/_shared/rest/`) serves
1324
+ The indexed hatch (`src/http/hatch.ts`) serves
1328
1325
  `<vendor>_api_search`, `_api_details`, `_api_read`, and `_api_write` over an
1329
1326
  `OperationIndex` that `pnpm run providers:spec` compiles offline from the
1330
- provider's pin (`evidence/openapi.json`; `openapi.source.json` until its step 1)
1331
- into `openapi.generated.ts`. A `vendored: true` pin compiles the reviewed
1332
- conversion in `evidence/openapi.document.json` instead of fetching, and the
1333
- generated header records that document's digest beside the pin's, so the
1334
- offline freshness check sees a changed conversion.
1327
+ provider's pin (`evidence/openapi.json`)
1328
+ into `openapi.generated.ts`. A `vendored: true` pin compiles offline from
1329
+ the reviewed conversion in `evidence/openapi.document.json`, or derives a
1330
+ deterministic Discovery conversion from its pinned original as described below.
1331
+ The generated header records the converted document's digest beside the pin's,
1332
+ so offline freshness sees a changed conversion.
1335
1333
  Each call is matched to an operation and checked against its parameters before
1336
1334
  transport. Resolved path parameters are validated before authentication or dispatch,
1337
1335
  including pinned enums and numeric bounds. Number path values must decode to canonical finite ASCII decimals without
@@ -1340,16 +1338,26 @@ canonical ASCII decimal safe integers: `0`, positive decimals without leading
1340
1338
  zeros, or negative decimals without leading zeros. `-0`, leading `+`, whitespace,
1341
1339
  exponents, decimal points and non-ASCII digits are refused. Negative integers
1342
1340
  remain valid when the pin has no minimum excluding them. String-valued ids keep
1343
- their declared string contract; `_api_read` admits GET and the vendor's reviewed read-only POSTs in
1344
- its handler, since classification is per tool name. Vendors configure only a
1345
- transport, failure mapper, scope, framing, cursor extraction, a reviewed
1346
- value-safety table (required; see below), argument-dependent refusals, and an
1347
- idempotency header, plus optional hooks: `path` (fill default ids before
1348
- matching), `admit` (an awaited check in `callRest` every tool passes, such as
1349
- Cloudflare's account and zone pin), `result` (unwrap a vendor envelope;
1350
- redaction runs after it and before cursors and `select`), a reviewed
1351
- request-header allowlist, text bodies, and index `slashParams` that admit an
1352
- encoded `/` in a final key segment (`test/rest-connector.test.ts`).
1341
+ their declared string contract. `_api_read` admits only operations with explicit
1342
+ reviewed read verdicts, including GET/HEAD and read-only POSTs where declared;
1343
+ classification is per tool name. Providers declare a confined kit connection,
1344
+ a value-safety table (required;
1345
+ see below), and any framing, scope, paging or refusal hooks through the hatch
1346
+ binding. The connection owns authentication, transport, failure mapping and
1347
+ result safety. An index's `slashParams` can admit an encoded `/` in a reviewed
1348
+ final key segment. Current hatch admission, paging, privacy and one-send
1349
+ outcomes are exercised by the required `eval:outcomes` tasks against stateful
1350
+ vendors and HTTP MCP deployments. `test/provider-hostile-response.node.test.ts`
1351
+ commits real HTTP writes before returning HTML, malformed JSON or an oversized
1352
+ acknowledgement, then reconciles vendor state with exactly one physical send.
1353
+ `test/provider-privacy-journey.node.test.ts` checks credential echoes over HTTP.
1354
+ Focused provider suites retain MIME/draft restrictions, revision conflicts,
1355
+ CCB routing, Planning Center product exclusions and deployment pins. Native
1356
+ HTTP framing, cursor and request-lifetime fault probes remain in the HTTP suites.
1357
+ The catalog-wide status sweep and its argument roster, catalog/ranking copies
1358
+ and unused paging strategy tests are retired under #1072. Provider workflows
1359
+ belong in the existing shared outcomes; a new tool requires no failure-matrix row.
1360
+ No legacy REST tool adapter remains.
1353
1361
  Large documents opt into generator options that drop restated operation ids
1354
1362
  and plain path parameters and cap one operation's details (`opBudget`).
1355
1363
  `numericBounds: true` preserves documented numeric minimum/maximum constraints
@@ -1364,11 +1372,10 @@ levels, 256 paths or 200 characters per path; overflow or an unresolved
1364
1372
  reference omits that operation's whole response-field contract. Explicitly open
1365
1373
  roots (including root-array items) also leave fields absent. Empty,
1366
1374
  schemaless and non-JSON responses declare no fields. Request shrinking and
1367
- endpoint contract digests do not depend on this metadata. Legacy REST tools
1368
- retain their catalog and discovery behavior until each provider's step 2.
1375
+ endpoint contract digests do not depend on this metadata.
1369
1376
  Fields remain optional additive metadata, so a previously compiled
1370
1377
  index without the source bytes remains usable without inventing a response
1371
- contract. Vercel's step-2 pin review restores response metadata from the reviewed public
1378
+ contract. Vercel's pin includes response metadata from the reviewed public
1372
1379
  document; operations without declared response properties still refuse fields. Breeze's pin declares no response
1373
1380
  properties. GitHub's immutable official OpenAPI pin supplies its complete index and response fields; a reviewed repository allowlist controls dispatch. Natural queries with reviewed matches scope discovery to those matches and named-only operations; explicit paths and unmatched queries retain full-pin refusal discovery.
1374
1381
  `check:providers-generated` checks each index header against its source record
@@ -1406,7 +1413,7 @@ UTF-16 code units; full reconstruction must match its recorded exact length.
1406
1413
  These physical decode checks do not change request validation, schema traversal,
1407
1414
  search, refusal, result or discovery budgets. Generation and offline roundtrip
1408
1415
  tests must preserve every pinned logical contract; storage changes never accept
1409
- new upstream evidence or golden bytes. The compaction suites cover exact strings,
1416
+ new upstream evidence. The compaction suites cover exact strings,
1410
1417
  native Web Crypto identity, malformed references, lazy decoding, mutation
1411
1418
  semantics and every maintained provider.
1412
1419
 
@@ -1427,14 +1434,12 @@ every vendor ships one reviewed table through one mechanism
1427
1434
  signing, webhooks, drains, transfer, claim, and invite codes). It is the
1428
1435
  union of the detectors Cloudflare and Vercel shipped first, and
1429
1436
  deliberately over-inclusive. `providers:spec` writes
1430
- `evidence/value-safety.json` (`value-safety.candidates.json` until the
1431
- provider's step 1) when the source record sets
1437
+ `evidence/value-safety.json` when the source record sets
1432
1438
  `options.valueSafety` (vendor `operationWords`; Stripe's `expansions: false`
1433
1439
  skips id-or-object expansions, which are their own operations' candidates),
1434
1440
  stamped with the pinned digest, the detector format, and its options. The
1435
1441
  file is test evidence and never ships.
1436
- 2. **One reviewed verdict per candidate**, in the vendor's `safety.ts`
1437
- (`value-safety.ts` until its step 1):
1442
+ 2. **One reviewed verdict per candidate**, in the vendor's `safety.ts`:
1438
1443
  `refuse` (the generic tools refuse it before transport, naming the
1439
1444
  operation and the reason), `redact` (reviewed field paths), or `safe`, each
1440
1445
  with a reason. Paths are dot paths into the data a tool returns: a list on
@@ -1455,8 +1460,8 @@ every vendor ships one reviewed table through one mechanism
1455
1460
  otherwise. `providers:spec` derives the binding fields from the pinned
1456
1461
  schema, and the harness fails until the condition lists each one. Argument-dependent refusals (Stripe expansions,
1457
1462
  Vercel `decrypt`) stay in the vendor's `refuse` hook.
1458
- 3. **Redaction on every success body**, in `callRest` after `result` and
1459
- before cursors and `select`, so named tools, HEAD data, and uploads pass
1463
+ 3. **Redaction on every success body**, in the kit connection after `result`
1464
+ and before cursors and `fields`, so named tools, HEAD data, and uploads pass
1460
1465
  through it too: the operation's reviewed paths, then the key-name
1461
1466
  heuristic as defense in depth. The heuristic is the union of the former
1462
1467
  vendor engines: a credential word anywhere in a non-metadata name removes
@@ -1619,14 +1624,13 @@ response schema can return (through `options.valueSafety.dataRoot` for an
1619
1624
  envelope such as Cloudflare's `result`), and every resource rule path
1620
1625
  something the resource's schema can return. It stamps the paths that resolve
1621
1626
  into the candidates file and fails on the rest, unless the table's `absent`
1622
- field (`value-safety.absent.json` until the provider's step 1) acknowledges
1627
+ field acknowledges
1623
1628
  them with a reason (shared verdicts applied to operations whose schema lacks a
1624
1629
  path, or fields a schema leaves undeclared; such paths still apply at
1625
1630
  runtime).
1626
1631
 
1627
1632
  `test/fixtures/value-safety.ts` is the shared harness each vendor's
1628
- `value-safety.node.test.ts` (`provider.safety.node.test.ts` after its step 1)
1629
- runs; `reviewProblems` is pure, and
1633
+ `provider.safety.node.test.ts` runs; `reviewProblems` is pure, and
1630
1634
  `test/value-safety-harness.node.test.ts` proves wrong paths fail it. It fails
1631
1635
  on candidates from another pin, format, or option set; an unreviewed
1632
1636
  candidate; a verdict for an operation the index lacks; a table path the stamp
@@ -1653,232 +1657,116 @@ There are no hosted review maps, pins, drift comparisons or review UI fields.
1653
1657
  Catalog refresh activity still compares successive accepted catalog fingerprints
1654
1658
  and reports only added, removed and changed counts in the caller's partition.
1655
1659
 
1656
- #### Characterization goldens
1657
-
1658
- Every maintained provider with an `api()` surface has goldens under
1659
- `test/goldens/<provider>/`: the oracle a provider migration must match byte
1660
- for byte. `catalog.json` holds the connector metadata, the rendered guide,
1661
- and each tool's name, description, schemas, and annotations. `calls.json`
1662
- holds at least one fixture call per tool, then an echo call: the exact
1663
- requests sent (method, URL, sorted headers, body), grouped into causal
1664
- steps, and the agent-visible outcome. `failures.json` drives one read and
1665
- one write through 400, 401, 403, 404, 409, 422, 429 (with `retry-after`)
1666
- and 500 responses, a 401 whose message echoes every sent secret, a refused
1667
- connection, and a transport timeout (a `TimeoutError` after the request
1668
- left). `setup.json`, for a provider whose spec completes an OAuth consent,
1669
- holds the consent's steps. Calls run through `Registry` and
1670
- `InvocationService` with a real credential vault, so the outcome is what
1671
- `call_tool` returns before MCP rendering.
1672
-
1673
- `test/goldens/<provider>/spec.ts` says only how to build the provider and
1674
- which calls to make, including an `echo` call whose vendor reply carries the
1675
- text the harness passes. `test/goldens/harness.ts` owns everything else:
1676
-
1677
- - The fake network records each request as `new Request(input, init)`
1678
- builds it, so `init.headers` replaces a Request's headers as Fetch does,
1679
- and a body gets its implied `content-type`. Form bodies are recorded as
1680
- fields when they re-encode to the exact bytes sent; FormData as its parts,
1681
- with the runtime's boundary as `<boundary>`. A JSON body is recorded as
1682
- `json` alone only when it is exactly that value's compact serialization;
1683
- any other spacing, key order, or escape also keeps the exact `text`.
1684
- - A step loop drives each scenario under fake timers. It drains microtasks,
1685
- fires timers due now synchronously, and waits for request construction and
1686
- counted real work to finish. Newly waiting requests form one step, sorted
1687
- by method, URL, headers, and exact body. The loop releases **one answer at
1688
- a time**, running to quiescence after each. Previously recorded requests
1689
- keep release priority over new requests. Fixture updates capture canonical
1690
- cohort release order and reverse cohort release order, each with its own
1691
- fresh module graph, clock, network and cache namespace. Queue replies are
1692
- assigned in canonical request order in both runs; only answer delivery
1693
- changes. Steps remain readable admission cohorts, not simultaneous answers.
1694
- Workerd checks compare the canonical observation. In stored fixtures,
1695
- identical observations collapse to one
1696
- row; differing reverse observations appear in `variants`, each with
1697
- `order: "reverse"`, complete `steps`, optional `waitedMs`, and `result`.
1698
- Setup uses the same rule, with `{ steps, variants }` only when orders differ.
1699
- This bounded two-order model deliberately does not enumerate all interleavings.
1700
- - Every request records integer `after`: the number of answers delivered
1701
- when the provider called fetch, before harness jitter or body inspection.
1702
- It identifies a prefix of that run's release sequence; it includes auxiliary
1703
- requests and resets for setup and invocation. The canonical run releases
1704
- each cohort forwards, the reverse run backwards, with older cohorts first.
1705
- For concurrent A and B, C awaiting only B and C awaiting both have canonical
1706
- `after: 2`, but reverse `after: 1` and `after: 2` respectively. The differing
1707
- variant preserves that dependency. One integer per request keeps frontiers
1708
- linear, including a 300-page sequential call. A write sent before login and
1709
- a write duplicated concurrently or sequentially also differ.
1710
- - Distinct queued replies for indistinguishable concurrent requests are a
1711
- fixture authoring error: the harness rejects them with a diagnostic. Use
1712
- identical replies or a request discriminator the provider controls. The
1713
- arrival order of identical requests cannot assign distinct responses.
1714
- - `test/goldens/setup.ts` installs source dispatchers before a golden test
1715
- file imports any provider, connector or Effect module. `vi.resetModules()`
1716
- and dynamic imports refresh those graphs for each capture and release order.
1717
- The dispatchers retain their identity across captures: saved and prebound
1718
- functions, and functions captured by Effect, still consult the current
1719
- capture. Their defining prototypes are wrapped too. Native implementations
1720
- remain private to the source controller; outside captures the dispatchers
1721
- delegate unchanged, preserving Vitest's real clocks and runner timeouts.
1722
- - The supported asynchronous model is explicit: fake fetch answers; fake
1723
- timeout, interval and immediate timers, including `AbortSignal.timeout`; Web Crypto's promise-returning
1724
- subtle methods; Request/Response/Blob body reads (`arrayBuffer`, `blob`,
1725
- `bytes`, `formData`, `json`, `text`, where present); default stream-reader
1726
- `read`/`cancel` and stream `cancel`/`pipeTo`; and promises/`queueMicrotask` chains rooted in those sources or
1727
- synchronous work. Effect's scheduler and sleeps use the same microtasks
1728
- and fake timers. A synchronous TextDecoderStream pipeline is supported.
1729
- Timer delays must coerce to finite nonnegative integer milliseconds within
1730
- the signed 32-bit timer range; other delays poison the capture. This keeps
1731
- Date and nanosecond clocks integral. New host asynchronous sources must be
1732
- registered and counted before use.
1733
- Native CompressionStream/DecompressionStream, `scheduler.wait`, and
1734
- native socket/worker/event-source constructors are rejected explicitly,
1735
- including when their errors are swallowed by a provider. CompressionStream
1736
- async iteration bypasses the reader-method spy and cannot establish
1737
- quiescence. No golden may silently bless that path.
1738
- - A no-stimulus audit follows declared quiescence: request, counted-work,
1739
- timer, or call-settlement progress before an answer or clock tick fails
1740
- with an unsupported-source diagnostic. Waiting without a request, counted
1741
- work, or fake timer also fails. The audit is a secondary assertion: source
1742
- control starts at module load, and supported host promises and microtasks
1743
- are counted from entry through completion. Quiescence requires zero active
1744
- counted work, zero queued controlled microtasks, and no due timers; future
1745
- virtual timers are explicit harness stimuli. Unregistered native producers
1746
- are unavailable or throw, including saved constructors and swallowed errors.
1747
- `process.nextTick`, `process.uptime`, `Atomics.waitAsync`, native messaging
1748
- constructors, and performance timeline methods are unsupported. The
1749
- test-only `golden-source-boundary` transform rejects Node host-module imports
1750
- in provider graphs and rejects lazy module loading during scenario work,
1751
- before either can capture native references or schedule uncounted I/O. Only
1752
- the harness's fresh-graph loading phase admits test fixture imports.
1753
- Invalid captures cancel and drain their concurrent fake requests.
1754
- - Settle, rejected-capture cleanup, and final teardown pump controlled timers,
1755
- microtasks, and fake requests within the original 10,000-host-turn windows.
1756
- Only outstanding captured Web Crypto operations can extend a window: after
1757
- exhausting it, await a snapshot of those native operations to settle, then
1758
- resume with a fresh bounded window. Each phase allows at most 100 native
1759
- extensions and reports an explicit error on exhaustion. Web Crypto always
1760
- settles independently of the harness's fake network, timers, and producers.
1761
- Body reads and stream reads are counted for quiescence but cannot extend a
1762
- window: their producers may require a fake response, future virtual time,
1763
- or never complete. No producer attribution or stream constructor tracking
1764
- is needed. Pending native crypto never advances virtual deadlines or merges
1765
- request cohorts. Clock advancement remains limited to 1,000 ticks.
1766
- Unsupported producer dependencies reject within the turn bound; teardown
1767
- always clears timers and releases capture ownership, including after failed
1768
- construction and overlapping capture rejection. The next capture must work.
1769
- Each capture has an async-context epoch that closes before ownership is
1770
- released, even when its native extension cap is exhausted. Controlled-source dispatchers reject closed
1771
- continuations before touching another capture's state. Fake request entry,
1772
- admission, response delivery, and serialization check their owning epoch,
1773
- including after asynchronous body inspection. Late work cannot record into
1774
- or receive a response from a later capture, which never waits for it.
1775
- Closing also attaches rejection handlers to outstanding counted promises,
1776
- consuming abandoned native body-read rejections without awaiting them.
1777
- Source regressions explicitly assert either completion or bounded rejection
1778
- followed by recovery. Crypto-delay probes at 11,000 and 100,000 host turns
1779
- must complete with unchanged observations; producer-fed bodies need not.
1780
- - The network answers in zero virtual time. Before advancing to the next
1781
- timer, the loop requires eight quiet real event-loop turns and an audit.
1782
- A row records nonzero `waitedMs`, the virtual time spent on provider
1783
- timers. Elapsed-time readings count only those timers. A timer of 0 ms
1784
- set outside a timer callback is due at once and stays in the current
1785
- cohort. Unjoined timers at completion fail. Since `AbortSignal.timeout`
1786
- cannot be cancelled, remaining signal deadlines fire during teardown, outside
1787
- `waitedMs`; any resulting request or result mutation fails. Every successful
1788
- drive and scenario boundary has zero outstanding controlled work and timers.
1789
- - Auxiliary routes answer token exchanges and other requests that are not
1790
- the tool's own, and are recorded by name with headers and body. A JWT in a
1791
- header or field is recorded as its decoded header and claims, with
1792
- `<signature>` for the per-run signature.
1793
- - `setup` runs before each scenario; its requests must be identical in
1794
- every scenario and are recorded once.
1795
- - Determinism: a fresh fake clock per scenario (timers, `Date`, and
1796
- `performance`, and Node `process.hrtime`/`hrtime.bigint`, starting at
1797
- 2026-01-02T03:04:05Z), counted
1798
- `crypto.randomUUID`, and fixed `crypto.getRandomValues` and `Math.random`,
1799
- all restarted per scenario. `create(scenario)` receives a slug unique in
1800
- the process: the scenario name plus a per-capture suffix the goldens never
1801
- show. Load-time hrtime dispatchers also control Effect wall and monotonic
1802
- nanoseconds on the virtual clock. Default-date Intl formatting also reads
1803
- the virtual wall clock.
1804
- A process-wide cache (Google's delegated tokens) never carries
1805
- over from an earlier scenario or capture.
1806
- - Secrets: every credential field and secret becomes `<secret:field>`, with
1807
- HTTP Basic shown decoded. Before that placeholdering, the harness fails
1808
- the capture if any secret reaches a caller-visible result (INV-5). The
1809
- guard decodes the result itself: JSON escapes, percent escapes in either
1810
- hex case, and base64 or base64url at any alignment, up to three layers
1811
- deep. It also finds any start of a secret that reaches 12 characters past
1812
- its public framing, so a truncated echo is a leak. Framing is a PEM armor
1813
- line and the DER structure that opens every key of its type (tags,
1814
- lengths, version, algorithm identifier), which guides and example keys
1815
- print. A later fragment, a shorter one in any encoding, or a secret with
1816
- its case changed is not detected. A base64 run is decoded only from 11
1817
- characters (8 bytes), shorter than the base64 of any start the guard
1818
- looks for.
1819
- - The echo call carries every secret not listed in `unsent` in each
1820
- encoding redaction covers: raw, percent-encoded with upper- and lowercase
1821
- hex, base64, unpadded base64url, and `\uXXXX` escapes with upper- and
1822
- lowercase hex, plus the base64 of each `basic` pair. Every sent secret
1823
- contains `/`, `+`, and `=`, so its percent and base64url forms differ from
1824
- its raw and base64 forms. The `401 echo` case echoes the raw secrets only
1825
- unless the spec sets `errorEcho: "all"`: a provider that caps a vendor
1826
- message before redaction sees it would leak the start of a longer form its
1827
- cut goes through. The Google Workspace specs set it, since Google redacts a
1828
- message whole before cutting it to 500 characters. Their `401 echo` carries
1829
- `errorEchoForms`: every form above, the `Bearer` and `token` framings, and
1830
- an HTTP Basic pair holding the token as header, base64 and base64url.
1831
-
1832
- Object keys keep the order the provider produced. A migration changes the
1833
- provider, never the spec or harness.
1834
-
1835
- `test/goldens.test.ts` compares every provider on Node and workerd. It fails
1836
- if a provider folder is neither covered nor listed as remote-MCP-only, a tool
1837
- has no call, or a golden file is missing or extra. Ordinary checks never write.
1838
- Node compares forward and reverse observations byte for byte; workerd compares
1839
- canonical observations. Each order starts a fresh module graph. Workers projection
1840
- removes variants only at harness observation positions, never from vendor fields
1841
- or schemas. Fixture updates retain both orders.
1842
- There are no characterization tiers, path classifiers, or planning-only runs.
1843
-
1844
- `test/goldens-harness.test.ts` keeps the source and mutation guards on Node:
1845
- replaced Authorization headers, changed auxiliary/login bytes, writes sent
1846
- early or twice, and missing secret-encoding redaction must alter a capture or
1847
- fail it. Mutation probes capture the affected call rather than repeating an
1848
- entire provider catalog. Redaction negative controls use Forms, GitHub, Breeze
1849
- and Tithe.ly to cover OAuth/Bearer, app-token, query-key and provider-kit lanes;
1850
- the ordinary goldens still check every provider's complete secret echoes.
1851
- The native-extension budget is checked directly at its 100-extension boundary,
1852
- and a gated closed-epoch continuation must fail before entering the next
1853
- capture's network. Genuine crypto completion, rejection, late dispatch and
1854
- producer-fed stream probes retain their native settlement coverage without
1855
- repeating a million-turn synthetic delay. Ordinary runs use one source-probe schedule. Nightly Node runs set
1856
- `CONNECTA_GOLDENS_DETERMINISM=1` for an identical repeat, provider jitter seeds
1857
- 1 and 2, and the complete source-probe jitter matrix. Small native-source probes also run on
1858
- workerd: `scheduler.wait`, CompressionStream, saved timers/microtasks and
1859
- Effect scheduling, prebound crypto/clocks, module freshness, runner clocks,
1860
- and Blob/TextDecoderStream promise settlement. Runtime-specific cases carry
1861
- Vitest's `workers` tag; broad cases carry `node`, which the Workers project
1862
- skips. Other mixed transport/auth/runtime suites use the same tags to retain
1863
- native fetch, request/response streams, deadlines, signals, crypto and SDK
1864
- settlement without duplicating their policy matrices. `vitest.config.ts`
1865
- selects these files with globs that tolerate test-file deletion. Portable
1866
- filenames alone do not enroll a new file in workerd.
1867
-
1868
- Repository verification policy, CI requirements, and exact commands live in
1869
- [AGENTS.md](https://github.com/zackbart/connecta/blob/main/AGENTS.md#verification).
1870
-
1871
- JWT fixture specs import fixed, public throwaway RSA PEM keys, with an
1872
- import/sign/verify self-test. This avoids expensive key generation on every
1873
- fresh module evaluation without changing characterized JWT claims or bytes.
1874
- The harness never caches evaluated module graphs. Global controls prohibit
1875
- `it.concurrent`; parallelism must use isolated files/workers. Transformed code
1876
- may be cached.
1877
-
1878
- `pnpm run goldens:update [provider...]` rewrites the named goldens (all
1879
- when none are named) on Node; it is not part of `check`. A PR
1880
- that changes agent-facing output on purpose regenerates the affected goldens
1881
- and says why in its description; any other golden diff is a regression.
1660
+ #### Behavioral evidence (contributor)
1661
+
1662
+ The characterization snapshot engine, provider JSON snapshots, source scheduler
1663
+ and its self-tests are retired under
1664
+ [#1072](https://github.com/zackbart/connecta/issues/1072). Provider changes no
1665
+ longer require golden enrollment, snapshot updates, byte equivalence or nightly
1666
+ capture determinism. Production invariants remain unchanged.
1667
+
1668
+ Use the existing stateful fixture vendors and published-edge deployment adapters:
1669
+
1670
+ - `pnpm run eval:outcomes` drives representative joins, retained paging, endpoint
1671
+ refusal, auth handoff, value safety and recovery after committed refunds,
1672
+ cancellations, DNS and environment updates, plus a single GitHub draft release
1673
+ and Google document partial creation and shared-drive permissions. Graders inspect
1674
+ independent downstream state and the physical mutation ledger, and reject
1675
+ wrong targets, duplicate writes, missing completion and interrupted trials.
1676
+ Every reference also rejects a fabricated correct answer without the work.
1677
+ Promoted read journeys reject erased MCP data even with the vendor ledger intact.
1678
+ - `pnpm run eval:smoke` boots the Node template, Node eval deployments and native
1679
+ Workers deployments, including the actual QuickBooks and Granola providers, then exercises
1680
+ MCP and the operator page.
1681
+ - The shared `granola-workspace-journey` outcome uses actual provider reads,
1682
+ independent fake meeting state and physical cursor/filter requests on both
1683
+ Node/SQLite/QuickJS and native Workers/D1. It covers transcript-too-large
1684
+ recovery, empty intermediate pages, selected fields, withheld photo/credential
1685
+ values and shared-vault reuse after application reconstruction. No-op,
1686
+ fabricated-read and erased-delivery controls must fail.
1687
+ - `test/identity-write-journey.node.test.ts` uses the existing Node deployment
1688
+ adapter, stateful MCP fake, SQLite vault and QuickJS to grade admitted human
1689
+ and machine identities, pool isolation, fail-closed discovery, endpoint and
1690
+ connector policy, physical mutation counts, ambiguous-write reconciliation,
1691
+ credential ownership and payload-free activity. Independent decoding checks
1692
+ returned private values and credential echoes; positive record facts must
1693
+ still arrive. An explicitly writable pool also exercises reopening a
1694
+ read-only deployment without bypassing connector policy.
1695
+ - `test/cancellation-journey.node.test.ts` observes a queued client's departure
1696
+ without another vendor send, and an active client's departure after the
1697
+ vendor commits. The vendor must see its held response socket close before
1698
+ releasing it; a later MCP read recovers the committed intent exactly once.
1699
+ `test/cancellation-faults.test.ts` keeps signal-less token-resolution,
1700
+ warmed-credential digest, stalled body-cleanup and abort/grant races on Node
1701
+ and workerd. These replace the universal Promise-method/seam/owner matrix
1702
+ and its enrollment self-test, plus migration-only runtime wrapper checks.
1703
+ - `test/browser/operator-flows.spec.ts` serves the actual operator shell and
1704
+ routes over TCP with file-backed SQLite. Sign-in, Settings provenance, OAuth
1705
+ connect/disconnect and credential save/test/replace/remove survive closing and
1706
+ reopening the app, database and vault. An independent SQL connection reads
1707
+ trigger counts: one save, one replacement, one removal, and no credential
1708
+ writes from reads or a rejected replacement. A real SQL trigger failure leaves the old
1709
+ credential usable after restart. MCP calls verify that those edits preserve
1710
+ the reader pool's actual read access and write refusal. Activity renders
1711
+ successful calls recorded before restart without either credential value.
1712
+ - The existing Node-template `eval:smoke` target constructs invalid config from
1713
+ published imports before any I/O and reuses a stored token after restarting
1714
+ the consumer process. Its Worker-fakes target saves a personal credential in
1715
+ Chromium, refuses another owner's use, saves that owner's invalid credential,
1716
+ then restarts workerd on the same D1 directory. Actual downstream records
1717
+ remain readable only to the correct owner. Direct SQL inspection finds two
1718
+ distinct durable encrypted rows and exactly one committed save for each.
1719
+ - Keep focused SQL batch/schema/retention rollback, clock-skew and absolute
1720
+ expiry, NUL/UTF-8 and literal-prefix, cross-connection claims, cancellation,
1721
+ corrupt-row and tracing-secrecy probes. Keep operator identity/slot fences,
1722
+ deadlines, CSRF, restricted-view projection and sink secrecy probes. These
1723
+ cover faults that a successful browser journey cannot reproduce. Retired
1724
+ evidence includes the key-prefix source scanner, config expected-object
1725
+ matrices, operator structure snapshots and native-composition sentinels.
1726
+ - `test/provider-privacy-journey.node.test.ts` sends credentials through real
1727
+ HTTP MCP and a maintained API provider. Unknown vendor fields and keys carry
1728
+ raw, escaped, percent-encoded, base64 and Basic echoes through direct calls,
1729
+ QuickJS programs, failure and recovery. The independent decoder in
1730
+ `test/helpers/secret-echoes.ts` checks the wire responses for secret fragments;
1731
+ it does not normalize them to placeholders or compare saved output.
1732
+ - `test/provider-hostile-response.node.test.ts` reconciles real HTTP mutations
1733
+ after HTML, malformed JSON and oversized acknowledgements with one physical
1734
+ send. It distinguishes Stripe's reviewed pre-execution 401 refusal, and checks
1735
+ read failure facts, secrecy and recovery through direct and QuickJS calls.
1736
+ `test/provider-failure-sweep.test.ts` retains only concrete auxiliary, composite,
1737
+ in-flight and untracked-call fault probes; no provider/tool argument roster or
1738
+ catalog/finalizer agreement sweep remains. Existing
1739
+ `test/sent-secrets.test.ts`, `test/sent-secret-output-boundary.test.ts`,
1740
+ `test/request-secret-redaction.test.ts` and `test/catalog-secret-redaction.test.ts`
1741
+ cover secrecy before projection, truncation, caching, paging and diagnostics.
1742
+ - `test/write-evidence.node.test.ts`, `test/remote-mcp-attempts.node.test.ts` and
1743
+ `test/oauth-credential-attempts.node.test.ts` inspect physical socket sends.
1744
+ Native transport parity, OAuth and write-provenance suites retain their
1745
+ workerd coverage. The shared throwaway RSA key in `test/fixtures/rsa.ts` is
1746
+ used by write-provenance and unknown-write-advice fixtures.
1747
+ - The request, catalog, auxiliary-call and renewal lifetime
1748
+ suites, plus `test/auth-admission-binding.test.ts`, exercise cancellation,
1749
+ held native work and garbage collection. These test actual request ownership;
1750
+ the retired capture scheduler's source guards were only harness constraints.
1751
+
1752
+ The remaining probes defend distinct reachable failures: auth admission and
1753
+ native scheduler ownership, grant/callback fencing and refresh coordination,
1754
+ SDK replay/redirect/SSE attempts, nested write provenance and refusal evidence,
1755
+ unawaited program drain and failed-program accounting, catalog drift and paging
1756
+ revocation, and hostile serializers, structural echoes, truncation and persisted
1757
+ pages. Broad scripted-executor policy/privacy cross-products and repeated
1758
+ post-401 result/error-shape tables are retired. Protocol claims link executable
1759
+ evidence files in `spec/coverage.json`; the invariant contracts above are defended
1760
+ by the actual behavior assertions in these journeys and focused probes.
1761
+ The required CI gate includes build/declarations, Node and Workers probes,
1762
+ outcomes, browser flows, installed consumers and Docker, audits and real Eve
1763
+ compatibility. Further contributor cleanup is tracked in #1072.
1764
+
1765
+ Add a compact fault journey only for a meaningful outcome those suites cannot
1766
+ observe. Reuse their fixtures and adapters; do not reintroduce a snapshot
1767
+ format, module loader or virtual scheduler. Workerd enrollment is for native
1768
+ fetch, streams, Web Crypto, lifetime and request-byte behavior, as listed in
1769
+ `vitest.config.ts`; pure logic runs on Node.
1882
1770
 
1883
1771
  ## Optional deployment modules
1884
1772
 
@@ -1996,9 +1884,9 @@ declarations; elsewhere it lives in an unexported function or in
1996
1884
  (`ConnectorCallError`, `ExecutorAdmissionError`, `CallAdmissionError`) because
1997
1885
  callers and tests check `instanceof`, `name`, and `message`.
1998
1886
 
1999
- Effect callers skip the Promise and take the program: `admit` and
2000
- `acquireScoped` for request admission (`src/runtime/admission.ts`), `admitCall`
2001
- and `acquireCallScoped` for call admission, `closeScope` and `closeScopeOnExit`
1887
+ Effect callers skip the Promise and take the program: `admit` for executor
1888
+ admission (`src/runtime/admission.ts`), `admitCall` and `acquireCallScoped` for
1889
+ call admission, `closeScope` and `closeScopeOnExit`
2002
1890
  for a connector scope, `withDeadlineEffect` where Promise code has
2003
1891
  `withDeadline`. The build prunes every declaration no `exports` target reaches,
2004
1892
  and `pnpm run check:declarations` fails if what remains names an Effect type.
@@ -2152,8 +2040,7 @@ never-settling evaluation/host calls, late rejection, execute-once ownership and
2152
2040
  original acquisition errors in workerd. `test/quickjs-pool.node.test.ts` covers
2153
2041
  readiness release, stale/malformed IPC, late host failures, backoff and bounded
2154
2042
  kill. Real Worker and QuickJS guest contracts, the HTTP Worker budget/queued
2155
- request fixture and native-output suites supply runtime parity evidence;
2156
- provider goldens do not execute a sandbox.
2043
+ request fixture and native-output suites supply runtime parity evidence.
2157
2044
 
2158
2045
  ### Native SQL storage (contributor)
2159
2046
 
@@ -2219,8 +2106,8 @@ published storage interfaces.
2219
2106
  The synchronous state-file parser, validation, file read, and one atomic
2220
2107
  SQLite import remain native synchronous leaves because `importStateFile` is a
2221
2108
  published synchronous API. `openSqlite` retains file modes, WAL, busy timeout,
2222
- and database ownership. `test/sql-effect-contract.ts` runs native-path,
2223
- affected-row, 50-claim, cancellation, and tracing checks on SQLite and native
2109
+ and database ownership. `test/sql-effect-contract.ts` retains affected-row,
2110
+ 50-claim, typed-failure, cancellation, and tracing probes on SQLite and native
2224
2111
  D1. `test/kv-to-d1.test.ts` also reuses stores across separate workerd requests;
2225
2112
  the existing SQL contracts prove rollback, database-clock TTL, encodings,
2226
2113
  activity upgrades, and copy recovery.
@@ -2283,9 +2170,12 @@ An accepted write's blocked retry retains its original HTTP status; a slot
2283
2170
  occupied by an auxiliary read instead names the separate write step needed.
2284
2171
  Structured resend advice reaches output only when the core permits it. Generic
2285
2172
  unknown writes retain the core's diagnostic wait; Q8 removes it. The mapping
2286
- adds no Promise entry or lifetime owner. The rule tables in `http-kit.test.ts`,
2287
- Stripe's sixteen-branch comparison and `kit-core-verdicts.test.ts` establish
2288
- these internal contracts. Maintained API providers use the kit through their
2173
+ adds no Promise entry or lifetime owner. `provider-failure-sweep.test.ts`,
2174
+ `guarded-attempts.node.test.ts`, `call-services.test.ts` and the native
2175
+ transport suites exercise these contracts through invocation, physical sockets
2176
+ and request closure. `http-kit.test.ts` retains focused numeric/text fact,
2177
+ request-equivalence and bulk-capacity fault probes. The migration-era
2178
+ kit/core verdict comparison is retired under #1072. Maintained API providers use the kit through their
2289
2179
  explicit provider subpaths; it stays off the root import graph and published
2290
2180
  declarations expose Promises.
2291
2181
 
@@ -2364,15 +2254,13 @@ inventories, and stale fallback cannot authorize post-entry auth recovery.
2364
2254
  ### Contributor provider kit
2365
2255
 
2366
2256
  Provider declarations use `src/http/vendor.ts` for HttpApi operations and
2367
- `src/http/tools.ts` for list, get, read, write and action builders.
2257
+ `src/http/tools.ts` for list, get, read and write builders.
2368
2258
  `src/http/provider.ts` composes them with `defineProvider`; it returns the
2369
2259
  ordinary Promise-based Connector factory. The kit stays outside the root
2370
- graph and its Effect types are internal. Tithe.ly is the first provider on
2371
- it (B.5): `api.ts` declares the vendor, `tools.ts` the tools, and its goldens
2372
- are unchanged.
2260
+ graph and its Effect types are internal. In each provider, `api.ts` declares
2261
+ the vendor and `tools.ts` the tools.
2373
2262
 
2374
- Decision 0011's standard surface (Tithe.ly's step 2) adds four kit pieces.
2375
- A `list` without the legacy `key` returns `{ items, page }`, with
2263
+ The standard `list` builder returns `{ items, page }`, with
2376
2264
  `page.nextCursor` only while `hasMore`, and the kit appends `limit` (the
2377
2265
  declared default and maximum), `cursor` and `fields` to the tool's filters;
2378
2266
  `read` and `get` take `fields: true`. `src/http/fields.ts` narrows after every
@@ -2460,7 +2348,7 @@ A refused method outside a read/write tool's input schema is inspected through
2460
2348
  Gmail's 49 non-GET refusals do not add a method field or a write hatch, and Forms'
2461
2349
  refused DELETE remains outside its write enum. GitHub's refused raw PUT merge
2462
2350
  is likewise outside its write enum; its named guarded alternative is unaffected.
2463
- These 51 schema refusals happen
2351
+ Such schema refusals happen
2464
2352
  before authentication or I/O; details exposes the same reviewed reason as search.
2465
2353
  Every schema-reachable refused operation still fails with that reason before
2466
2354
  authentication or dispatch. This is policy inspection, never execution admission.
@@ -2611,12 +2499,11 @@ storage loses them with the store. Key-load outages or corrupt stored keys
2611
2499
  produce retryable `unavailable`, naming the cursor signing key without its
2612
2500
  value. See [cursor-key recovery](./deploying.md#recover-a-cursor-signing-key):
2613
2501
  after repairing/deleting a corrupt key, restart every process/isolate to clear
2614
- cached keys. Pre-upgrade cursors require a new first page. Offline goldens
2615
- preseed a fixed key only in their harness.
2502
+ cached keys. Pre-upgrade cursors require a new first page.
2616
2503
 
2617
2504
  The helper derives connection metadata and probe messages from
2618
- validated options and still accepts complete legacy usage guides for compatibility.
2619
- All maintained providers have completed the standard-surface migration.
2505
+ validated options and renders every maintained guide through
2506
+ `ProviderContext.usageGuide`.
2620
2507
  Candidate checks can refuse before authentication while
2621
2508
  preserving the provider's exact diagnostic. Its optional `authScope(options)`
2622
2509
  selector fixes OAuth grant ownership from deployment mode at construction;
@@ -2624,8 +2511,7 @@ CCB uses shared System Auth grants and personal Identity Auth grants. Tool
2624
2511
  arguments cannot select a grant's owner. On Node, every maintained-provider
2625
2512
  request uses the owned sender `listen()` installs, reads included. Without it,
2626
2513
  maintained-provider writes and reviewed POST reads are refused before sending;
2627
- suites exercising those requests configure the sender themselves, as the goldens
2628
- harness does. Anything a connection
2514
+ focused suites exercising those requests configure the sender themselves. Anything a connection
2629
2515
  caches across calls, such as its typed HttpApi client, is built with no
2630
2516
  services, because Effect constructors close over the context they run in and a
2631
2517
  cached value would otherwise keep its first caller's request alive (INV-7).
@@ -2669,8 +2555,20 @@ All six Google Workspace products use the shared standard-surface support.
2669
2555
  archived exact-byte official Discovery documents into deterministic OpenAPI.
2670
2556
  The primary vendored pin retains the official URL, revision and source digest;
2671
2557
  its `discovery` relation names the sibling source pin and normalizer format.
2672
- Generation and offline freshness reproduce the conversion, and the generated
2673
- module records its independent document digest. Full source method inventory
2558
+ The sole retained document is `evidence/discovery.document.json`; no converted
2559
+ `openapi.document.json` is retained for these pins. Generation and offline
2560
+ freshness validate the original bytes against `discovery.json` and the primary
2561
+ pin, then derive the conversion in memory, including reviewed summary overrides.
2562
+ Its digest uses two-space JSON indentation and a terminal newline; the generated
2563
+ module records that independent document digest, preserving freshness checks
2564
+ for changes to the normalizer or summaries. This supersedes Decision 0011's
2565
+ retained-conversion requirement for deterministic Discovery evidence. Frozen
2566
+ measurements read those same provider-owned originals but validate the existing
2567
+ `test/fixtures/google-discovery/manifest.json` digests independently: a provider
2568
+ pin update must fail the historical measurement rather than silently rebase it.
2569
+ That reviewed pin-change PR must re-measure and update the product's manifest
2570
+ entry and the Forms #1009 drift-check digests when applicable, or retire the
2571
+ measurement. Full source method inventory
2674
2572
  and canonical source-to-relative-path mappings survive normalization. Gmail's
2675
2573
  source `userId` becomes deployment-owned `me`; runtime paths are relative to
2676
2574
  the existing connection root. Reserved Slides ids remain one encoded segment.
@@ -2692,13 +2590,13 @@ independent batch-kind, revision and resource guards. Google indexes explicitly
2692
2590
  set `pathMatching: "uri-template"` on `OperationIndex` to handle encoded literal
2693
2591
  collisions and parameter action suffixes. Other indexes retain exact literal
2694
2592
  segments and their existing refusal ordering. The matching mode also binds
2695
- discovery cursors. An indexed `googleClient` requires each named request's declared
2696
- template and refuses a substituted id resolving to another operation before
2697
- grant evaluation. Products opt in with `googleClient(connection, title,
2698
- { standard: true, index })`; their requests carry `template`.
2593
+ discovery cursors. `googleClient(connection, index)` requires each named request's
2594
+ declared `template` and refuses a substituted id resolving to another operation
2595
+ before grant evaluation. Every maintained Google product uses this indexed
2596
+ client; there is no unindexed settlement mode.
2699
2597
  Both the client and `googleHatchBinding(connection, { index, review })` require
2700
2598
  the explicit URI-template mode at construction. The hatch requires the binding's
2701
- exact index identity. Standard clients and Google bindings reject a missing
2599
+ exact index identity. Clients and Google bindings reject a missing
2702
2600
  index with an explicit construction error. The provider-standard suite checks
2703
2601
  actual hatch construction through every Google product fixture, requiring its
2704
2602
  Google binding with the same connection and index. The Google binding
@@ -2707,7 +2605,7 @@ dispatch.
2707
2605
 
2708
2606
  The generator's `allSuccessResponses: true` option unions JSON response fields
2709
2607
  from every 2xx. Existing providers keep the first JSON success contract until
2710
- their own reviewed regeneration; no committed provider index changes here.
2608
+ their own reviewed regeneration.
2711
2609
 
2712
2610
  `src/providers/_shared/google/hatch.ts` supplies JSON framing over the existing
2713
2611
  confined `Connection.sendPath`. It retains the hatch's origin/media guards,
@@ -2734,17 +2632,16 @@ For example, a direct value-mode result has outer `result.data`, the hatch's
2734
2632
  `result.data.page.nextCursor`, and vendor JSON at `result.data.data`:
2735
2633
  `call_tool({ address: "crm.forms_api_read", args: { path:
2736
2634
  "/forms/form_1/responses", cursor: previous.data.page.nextCursor },
2737
- resultMode: "value" })`. This is an envelope illustration for an opted-in
2738
- provider, not a claim that the Forms migration has shipped.
2635
+ resultMode: "value" })`. Google Forms uses this continuation envelope.
2739
2636
 
2740
2637
  `googleErrors(product, { standard: true })` declares the product's 404 meaning
2741
2638
  and uses common status fallbacks; revision-conflict meanings require a
2742
- separate declaration. Standard-mode `googleClient` preserves failure phase
2639
+ separate declaration. `googleClient` preserves failure phase
2743
2640
  metadata for partial-create recovery while leaving settlement and wording to
2744
2641
  the kit. Its incomplete-body wording covers JSON and binary reads without
2745
- claiming that binary success was expected to be JSON. Legacy mode retains
2746
- its catalog and failure bytes. No shared-core auxiliary-write outcome change
2747
- is part of this opt-in support.
2642
+ claiming that binary success was expected to be JSON. `googleGrant` still uses
2643
+ the nonstandard `googleErrors(product)` mapping for delegated-token rejection;
2644
+ that grant contract is separate from resource-request settlement.
2748
2645
 
2749
2646
  Drive's two-request reads also declare fixed steps: `get_file_content` uses
2750
2647
  `metadata` and `content`, and non-root `list_folder_items` uses `folder` and
@@ -2755,10 +2652,8 @@ Gmail declares separate initial and body-download steps for `get_message`,
2755
2652
  each of up to 25 summary reads, and `get_thread` names each stored body in
2756
2653
  Gmail's 100-message conversation limit. Serving these reads as writes keeps
2757
2654
  every request available once.
2758
- The layer's request adapter keeps the legacy wording of a served write whose
2759
- answer proves nothing (no answer, a 5xx, a redirect, or an unreadable 2xx) and
2760
- reports how far a failed request got. The core still decides every write's
2761
- outcome. Gmail's auxiliary draft and reply lookups pass both `effect: "read"`
2655
+ The request adapter reports how far a failed request got; the kit maps the
2656
+ failure and the core decides every write's outcome. Gmail's auxiliary draft and reply lookups pass both `effect: "read"`
2762
2657
  and a construction-declared step: the guarded client's early reservation uses
2763
2658
  that named slot, while the ledger marks the request auxiliary. A failed lookup
2764
2659
  keeps its read verdict and cannot make an unsent draft write unknown.
@@ -2767,7 +2662,7 @@ Sheets declares its seven API methods in `src/providers/sheets/api.ts`; its
2767
2662
  kit tools retain the private digest-bound cell cursor, legacy A1 path encoding,
2768
2663
  and create/append recovery advice. Its projections and the Google failure
2769
2664
  classifier read fields by the names Google gave them, which the kit's parse pass
2770
- keeps. Its catalog and guide stay unchanged in step 1.
2665
+ keeps.
2771
2666
 
2772
2667
  Google's request adapter also offers a reviewed binary send. It marks the
2773
2668
  operation `googleBytes` for the product's `binaryBodies` selector and forwards
@@ -2801,10 +2696,8 @@ Every defect from a run probe or its hooks uses the generic withheld notice,
2801
2696
  even without a kit dispatch, because a private transport leaves no kit visibility
2802
2697
  evidence. An open operation probe retains its original defect.
2803
2698
 
2804
- The REST bridge in `src/providers/_shared/rest/kit.ts` retains pinned index
2805
- validation and legacy hatch schemas while the kit owns tool leases, fixed write
2806
- capacity, transport, failures and result safety. It verifies schema equality
2807
- before restoring legacy catalog key order. `indexedVendor` derives operation
2699
+ `src/providers/_shared/rest/kit.ts` owns the shared REST call shapes, pinned
2700
+ schema conversion and indexed vendor declarations. `indexedVendor` derives operation
2808
2701
  metadata from the index and builds the full manifest lazily; the typed client
2809
2702
  contains only named operations and probes. Bulk indexed declarations preserve
2810
2703
  the OpenAPI brace paths verbatim and carry explicit parameter Schemas. They
@@ -2828,7 +2721,7 @@ transport idempotency key. These hints describe behavior; write routing and
2828
2721
  endpoint restrictions still apply. For example, a tool that only creates a new
2829
2722
  note can declare `destructive:false` without promising idempotency.
2830
2723
 
2831
- `restKitTools` may declare a `writeSteps` map whose values are `"once"`.
2724
+ Kit tools and the indexed hatch may declare a `writeSteps` map whose values are `"once"`.
2832
2725
  Construction freezes the map; every named step sends at most once and an
2833
2726
  undeclared step is refused before dispatch. Omitting it retains the single
2834
2727
  implicit write step. Auxiliary ownership reads in a write call retain that
@@ -2981,8 +2874,8 @@ result handling, reviewed value safety and the deployment privacy projection
2981
2874
  before paging or provider projections can read it. Read methods beyond GET
2982
2875
  and HEAD require a review. Construction fixes each write step's capacity;
2983
2876
  the guarded transport reserves it before preparation and the shared core
2984
- decides the whole call's write outcome. Dedicated upload builders wait for
2985
- the Google Drive migration in C.7.
2877
+ decides the whole call's write outcome. Drive uploads use write builders over
2878
+ reviewed raw-body sends.
2986
2879
 
2987
2880
  Reviewed path calls resolve their actual method and path through an indexed
2988
2881
  safety adapter; a provider-supplied template cannot bypass the policy.
@@ -3089,10 +2982,10 @@ same version to resolve a single copy. Connecta's own lockfile and packed
3089
2982
  install are checked for one copy (`test/package-surface.node.test.ts` and
3090
2983
  `scripts/check-package.mjs`).
3091
2984
 
3092
- The stable `4.0.0` release was re-evaluated on 2026-10-01 with
3093
- [`scripts/probes/effect-v4-evaluation.mjs`](https://github.com/zackbart/connecta/blob/main/scripts/probes/effect-v4-evaluation.mjs).
3094
- Run `pnpm run build`, then `node scripts/probes/effect-v4-evaluation.mjs output.json`.
3095
- The [raw observations](https://github.com/zackbart/connecta/blob/main/scripts/probes/effect-v4-evaluation-2026-10-01.json)
2985
+ The stable `4.0.0` release was re-evaluated on 2026-10-01 with this
2986
+ [historical probe source](https://github.com/zackbart/connecta/blob/1ab92695f2636f904274d900ce209553358ff1f3/scripts/probes/effect-v4-evaluation.mjs),
2987
+ retained in Git history rather than the current checkout.
2988
+ The [raw observations](https://github.com/zackbart/connecta/blob/1ab92695f2636f904274d900ce209553358ff1f3/scripts/probes/effect-v4-evaluation-2026-10-01.json)
3096
2989
  are synthetic Node requests and neutral esbuild bundles, not live-client or
3097
2990
  workerd lifetime verification. Bundle figures add representative prototypes
3098
2991
  alongside the current code; they do not claim savings from removing old code.
@@ -3101,7 +2994,7 @@ Two native input schemas with validation and JSON Schema rendering add 62,148
3101
2994
  bytes gzip to the root, taking it from 303,083 to 365,231 against a 339,526
3102
2995
  cap. Effect can reject excess properties when both decoding and rendering use
3103
2996
  `onExcessProperty: "error"`; its default strips them. The generated schemas
3104
- still differ from the exact meta-tool goldens, including record rendering and
2997
+ still differ from the published meta-tool schemas, including record rendering and
3105
2998
  composed numeric bounds. A Schema replacement would need to preserve that
3106
2999
  contract and memoized rendering. Both MCP SDK packages still depend on Zod,
3107
3000
  so changing our inputs alone does not remove Zod from an installation.
@@ -3193,7 +3086,8 @@ compiling and configuring the real thing.
3193
3086
  rejections are observed; dispatch and lease guards still contain detached
3194
3087
  work. Per-await I/O cancellation remains useful for releasing resources,
3195
3088
  while prompt refusal is enforced at the boundary
3196
- (`test/promise-boundary-lifetime.test.ts`). Invocation owns
3089
+ (`test/cancellation-faults.test.ts`, `test/operation-cancellation.test.ts`
3090
+ and `test/cancellation-journey.node.test.ts`). Invocation owns
3197
3091
  the recovery and logical-call records it reads after teardown. Closing an
3198
3092
  outer call also revokes nested calls paused in preparation. Request-owned
3199
3093
  MCP sessions and token flights outlive individual calls and close with the
@@ -3286,8 +3180,9 @@ compiling and configuring the real thing.
3286
3180
  at construction) and the predicate matched, which the ledger records on the
3287
3181
  request. Only Stripe declares it (`src/providers/stripe/api.ts`, reviewed
3288
3182
  as a `manual` check in its `drift.json`): an API v1 answer carrying Stripe's
3289
- `Request-Id`. `test/provider-failure-sweep.test.ts` holds that list to the
3290
- sources. Q8 is decided in one place, `settleWrite` in
3183
+ `Request-Id`. The real HTTP hostile-response journey checks this refusal
3184
+ against an ambiguous committed write; there is no copied declaration list.
3185
+ Q8 is decided in one place, `settleWrite` in
3291
3186
  `src/write-outcome.ts`, once per logical call and over every request it
3292
3187
  recorded. The invocation calls it for every failure of a served write: a
3293
3188
  thrown or mapped error, a custom connector's, a program's call, and its
@@ -3466,7 +3361,7 @@ compiling and configuring the real thing.
3466
3361
  (`keyProtectsLogicalCall`). Every resource request dispatched under the
3467
3362
  logical call, from any ledger, is recorded on it once per dispatch with
3468
3363
  its method and the genuine key it carried (`ProviderRequest.key`, set by
3469
- `callRest` only for a key fetch sends as given). The advice stands only when
3364
+ the kit's guarded transport only for a key fetch sends as given). The advice stands only when
3470
3365
  exactly one boundary was entered, the invocation's object owns it as for
3471
3366
  `knownForLogicalCall`, that boundary tracks every request, and exactly one
3472
3367
  dispatched request was a write, carrying the named key; a request counts as
@@ -3511,10 +3406,10 @@ compiling and configuring the real thing.
3511
3406
  reconciliation even with an idempotency key; direct transport calls
3512
3407
  without a served verdict can still prove repeatability, but only with a
3513
3408
  genuine key sent to a vendor that honors it (Stripe today, through
3514
- `idempotencyHeader`): the REST write tool refuses an `idempotencyKey` that fetch
3409
+ `hatch.idempotency`): the REST write tool refuses an `idempotencyKey` that fetch
3515
3410
  would send empty after trimming or would not send at all (CR, LF, NUL, any
3516
3411
  other control character but tab, DEL, or a code point past Latin-1), as
3517
- `invalid_args` before recovery is recorded, and `callRest` marks a request
3412
+ `invalid_args` before recovery is recorded, and the guarded transport marks a request
3518
3413
  repeatable only for a key fetch sends as given.
3519
3414
  `providerCallFailure` (`src/write-outcome.ts`) is the one finalizer for a
3520
3415
  direct write's failure: the `api()` handler boundary, a guarded transport
@@ -3536,29 +3431,17 @@ compiling and configuring the real thing.
3536
3431
  `write_outcome_unknown`. The caller's own abort reason still passes by
3537
3432
  identity for a read and for a served call, whose timeout passes through
3538
3433
  unchanged for the invocation to report.
3539
- The catalog-driven `test/provider-failure-sweep.test.ts` checks every API
3540
- provider/tool on Node, fails on missing provider/tool examples or a
3541
- dispatched failure bypassing the helper, and covers served write/read
3542
- overrides with HTTP 503 for every tool and a connection reset after send
3543
- for each provider/verdict representative. HTTP 401 recovery uses those
3544
- representatives plus the distinct composite, auxiliary, owner-lookup and
3545
- POST-as-read paths; every provider's full golden failure matrix still runs.
3546
- Shared sender and real-socket evidence below own status/reset permutations.
3547
- Local metadata
3548
- tools prove zero sends; composite calls prove each distinct request leaves
3549
- once. The round-5 cases additionally cover Docs creation with initial text,
3550
- composite success followed by refusal, GitHub preflight failures, typed
3551
- handler errors after successful sends, Forms cursor conflicts after 200,
3552
- generic-code vendor refusals, auxiliary failures after resource dispatch,
3553
- redaction of refusal errors, and concurrent direct-call ledger isolation.
3554
- The round-6 cases cover a composite write's early refusal while siblings
3555
- await credentials or are in flight, requests started after the call ended,
3556
- connect-phase errnos with each body kind (all unknown for a write, and a
3557
- direct read stays retryable), a request aborted with a refusal-shaped
3558
- reason, an errno outside fetch's network error, and
3559
- undeclared handlers whose untracked send precedes a typed failure. Each
3560
- catalog case also checks that the ledger recorded every resource request
3561
- the network saw, and the inventory that every API connector declares it.
3434
+ Shared provider outcomes and the real HTTP hostile-response journey check
3435
+ returned data, failure/recovery, privacy and physical writes without a
3436
+ catalog-wide status matrix. `test/provider-failure-sweep.test.ts` retains
3437
+ fault probes for Docs creation with initial text, composite success followed
3438
+ by refusal, GitHub preflight failures, typed handler errors after successful
3439
+ sends, Forms cursor conflicts after 200, generic-code vendor refusals,
3440
+ auxiliary failures after resource dispatch and concurrent direct-call isolation.
3441
+ It also holds siblings awaiting credentials or already in flight when another
3442
+ write fails, refuses requests after call closure, and probes network errors,
3443
+ refusal-shaped abort reasons and untracked sends. Native transport and
3444
+ request-lifetime suites retain their platform-specific evidence.
3562
3445
  `test/write-evidence.test.ts` uses real refused, reset, and held sockets on
3563
3446
  both runtimes: a refused write is unknown and a refused read retryable,
3564
3447
  including a write aborted with another fetch's real refusal as its reason
@@ -3831,7 +3714,7 @@ and workerd. `remote-mcp-native-bundle.node.test.ts` additionally loads an actua
3831
3714
  minified production bundle to verify call/cache registration, request Context,
3832
3715
  native storage, saved-original delegates, custom replacements and closed-owner
3833
3716
  refusal. Existing wire, physical-attempt, cache and OAuth lifetime suites remain
3834
- the compatibility evidence; provider golden observations remain unchanged.
3717
+ the compatibility evidence.
3835
3718
 
3836
3719
  ### Native upward MCP orchestration (contributor)
3837
3720