@zackbart/connecta 0.37.1 → 0.38.0

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 (168) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +2 -2
  3. package/bin/connecta.mjs +1 -39
  4. package/bin/version.mjs +1 -1
  5. package/dist/access-tokens.js +2 -4
  6. package/dist/agent-identity.js +1 -1
  7. package/dist/auth/clerk-sdk/generated.js +2 -1
  8. package/dist/auth/downstream-oauth.js +19 -153
  9. package/dist/auth/downstream-revocation.js +1 -1
  10. package/dist/auth/oauth-grant.js +11 -0
  11. package/dist/auth/oauth-token-response.js +1 -1
  12. package/dist/auth/vercel-agent.js +2 -1
  13. package/dist/auth-elicitation.js +2 -2
  14. package/dist/branding.d.ts +1 -15
  15. package/dist/branding.js +2 -2
  16. package/dist/bytes.js +42 -0
  17. package/dist/call-admission-context.js +2 -5
  18. package/dist/call-recovery.js +0 -3
  19. package/dist/catalog-fingerprint.js +2 -18
  20. package/dist/catalog-service.js +1 -1
  21. package/dist/config-defaults.d.ts +1 -0
  22. package/dist/config-defaults.js +1 -0
  23. package/dist/config-schema.d.ts +1 -1
  24. package/dist/config-schema.js +6 -2
  25. package/dist/config.d.ts +41 -14
  26. package/dist/config.js +21 -71
  27. package/dist/connectors/api-connector.js +4 -3
  28. package/dist/connectors/guarded-fetch.d.ts +0 -6
  29. package/dist/connectors/guarded-fetch.js +1 -11
  30. package/dist/connectors/remote-mcp.js +10 -43
  31. package/dist/connectors/resource-uri.js +0 -4
  32. package/dist/d1.d.ts +0 -89
  33. package/dist/d1.js +0 -34
  34. package/dist/downstream-input.js +2 -2
  35. package/dist/execute.js +22 -13
  36. package/dist/executor-result.js +2 -1
  37. package/dist/executors/quickjs-runtime.js +2 -25
  38. package/dist/executors/quickjs.js +1 -1
  39. package/dist/guest-runtime.js +5 -3
  40. package/dist/guest-types.d.ts +5 -5
  41. package/dist/http/client.js +1 -1
  42. package/dist/http/errors.js +2 -2
  43. package/dist/http/json-schema.js +1 -1
  44. package/dist/http/node-transport.js +0 -1
  45. package/dist/http/oauth.js +1 -1
  46. package/dist/http/paging.js +6 -9
  47. package/dist/http/provider.js +1 -1
  48. package/dist/http/safety.js +1 -1
  49. package/dist/http/services.js +1 -8
  50. package/dist/http/tools.js +1 -7
  51. package/dist/http/vendor.js +7 -7
  52. package/dist/identity.js +2 -6
  53. package/dist/invocation-auth.js +2 -1
  54. package/dist/meta-tools.js +27 -27
  55. package/dist/native-tools.js +2 -1
  56. package/dist/oauth-handoff.js +2 -2
  57. package/dist/operation-vocabulary.js +1 -1
  58. package/dist/operator-record.js +1 -49
  59. package/dist/operator-ui/contract.d.ts +2 -2
  60. package/dist/operator-ui/generated.js +3 -3
  61. package/dist/program-writes.js +3 -8
  62. package/dist/provider-call.js +0 -7
  63. package/dist/provider.d.ts +1 -1
  64. package/dist/providers/_shared/google/kit.js +1 -6
  65. package/dist/providers/_shared/google/service-account.js +1 -3
  66. package/dist/providers/_shared/google/workspace.d.ts +1 -1
  67. package/dist/providers/_shared/guide.js +3 -0
  68. package/dist/providers/_shared/json.js +12 -0
  69. package/dist/providers/_shared/rest/compact-index.js +1 -1
  70. package/dist/providers/_shared/rest/kit.js +1 -3
  71. package/dist/providers/_shared/rest/operation-index.js +1 -3
  72. package/dist/providers/_shared/rest/value-safety.js +26 -28
  73. package/dist/providers/breeze/api.js +2 -7
  74. package/dist/providers/breeze/index.js +4 -2
  75. package/dist/providers/breeze/tools.js +3 -4
  76. package/dist/providers/ccb/api.js +1 -6
  77. package/dist/providers/ccb/index.js +2 -1
  78. package/dist/providers/ccb/tools.js +1 -6
  79. package/dist/providers/cloudflare/api.js +2 -2
  80. package/dist/providers/cloudflare/index.js +2 -1
  81. package/dist/providers/cloudflare/safety.js +3 -3
  82. package/dist/providers/docs/tools.js +2 -10
  83. package/dist/providers/drive/tools.js +12 -25
  84. package/dist/providers/forms/tools.js +1 -9
  85. package/dist/providers/gmail/tools.js +5 -21
  86. package/dist/providers/overflow/api.js +1 -3
  87. package/dist/providers/overflow/index.js +2 -1
  88. package/dist/providers/overflow/tools.js +3 -7
  89. package/dist/providers/planning-center/api.js +2 -1
  90. package/dist/providers/planning-center/lib/constants.d.ts +1 -1
  91. package/dist/providers/planning-center/lib/json-api.js +1 -9
  92. package/dist/providers/planning-center/tools.js +2 -1
  93. package/dist/providers/sheets/tools.js +1 -9
  94. package/dist/providers/slides/tools.js +4 -13
  95. package/dist/providers/stripe/index.js +2 -1
  96. package/dist/providers/stripe/safety.js +2 -2
  97. package/dist/providers/tithely/api.js +2 -7
  98. package/dist/providers/tithely/index.js +3 -2
  99. package/dist/providers/tithely/tools.js +7 -5
  100. package/dist/providers/vercel/api.js +1 -6
  101. package/dist/providers/vercel/lib/pin.js +1 -1
  102. package/dist/providers/vercel/safety.js +1 -1
  103. package/dist/providers/vercel/tools.js +2 -1
  104. package/dist/redaction-marker.js +2 -2
  105. package/dist/registry.d.ts +1 -1
  106. package/dist/registry.js +5 -7
  107. package/dist/request-principal.js +1 -1
  108. package/dist/request-state.js +2 -2
  109. package/dist/routes/access-tokens.js +1 -1
  110. package/dist/routes/activity-disclosure.js +1 -1
  111. package/dist/routes/connect.js +2 -2
  112. package/dist/routes/credentials.js +1 -1
  113. package/dist/routes/mcp.js +4 -3
  114. package/dist/routes/oauth-management.js +1 -1
  115. package/dist/routes/operator.js +4 -3
  116. package/dist/routes/shared.d.ts +8 -8
  117. package/dist/routes/shared.js +9 -9
  118. package/dist/routes/ui-config.js +1 -1
  119. package/dist/routes/ui.js +1 -1
  120. package/dist/runtime/call-admission.js +1 -1
  121. package/dist/runtime/call.js +1 -1
  122. package/dist/runtime/settlement.js +1 -1
  123. package/dist/runtime/shared-read.js +2 -15
  124. package/dist/sent-secrets.d.ts +1 -2
  125. package/dist/sent-secrets.js +3 -8
  126. package/dist/server.js +4 -4
  127. package/dist/skills.js +8 -35
  128. package/dist/sqlite.d.ts +0 -19
  129. package/dist/sqlite.js +2 -83
  130. package/dist/storage/keys.js +16 -125
  131. package/dist/storage/sql-native.js +0 -101
  132. package/dist/storage/sql.d.ts +1 -24
  133. package/dist/storage/sql.js +1 -12
  134. package/dist/tool-error.js +4 -0
  135. package/dist/url-safety.js +0 -4
  136. package/dist/usage-guide.js +2 -2
  137. package/dist/version.d.ts +1 -1
  138. package/dist/version.js +1 -1
  139. package/dist/worker.js +1 -1
  140. package/documentation/README.md +6 -42
  141. package/documentation/architecture.md +86 -496
  142. package/documentation/auth.md +12 -25
  143. package/documentation/code-mode.md +90 -66
  144. package/documentation/deploying.md +19 -40
  145. package/documentation/integrating.md +4 -19
  146. package/documentation/meta-tools.md +6 -6
  147. package/documentation/migration-0.33.md +5 -5
  148. package/documentation/migration-0.34.md +2 -4
  149. package/documentation/migration-retired-layouts.md +74 -0
  150. package/documentation/operator-tests.md +19 -119
  151. package/documentation/operator-ui.md +3 -4
  152. package/documentation/provider-auth-migration.md +4 -10
  153. package/documentation/provider-migration-0.29.md +4 -15
  154. package/examples/worker/AGENTS.md +4 -6
  155. package/examples/worker/README.md +20 -115
  156. package/guides/connecting-agents.md +7 -30
  157. package/guides/how-it-works.md +2 -2
  158. package/guides/safety-and-trust.md +4 -1
  159. package/package.json +19 -19
  160. package/templates/node/README.md +9 -26
  161. package/templates/node/package.json +1 -1
  162. package/dist/auth/oauth-v2-migration.js +0 -135
  163. package/dist/provider-call-facts.d.ts +0 -115
  164. package/dist/provider-call.d.ts +0 -112
  165. package/dist/storage/d1-copy.js +0 -255
  166. package/dist/storage/sql-schema.d.ts +0 -6
  167. package/examples/worker/kv-to-d1.wrangler.jsonc +0 -26
  168. package/examples/worker/scripts/copy-kv-to-d1.mjs +0 -162
@@ -1,9 +1,7 @@
1
1
  # Migration to 0.34
2
2
 
3
- Use this guide when upgrading an existing deployment from 0.33 to 0.34.
4
- [Deployment upgrades](./deploying.md#upgrade-an-existing-deployment) cover the
5
- general procedure; [the agent index](./README.md) routes other work. Upgrades
6
- from earlier versions must also apply the intervening migrations.
3
+ Apply the [general upgrade procedure](./deploying.md#upgrade-an-existing-deployment)
4
+ when moving from 0.33 to 0.34, including intervening migrations for older versions.
7
5
 
8
6
  No storage migration, token rotation or required configuration field is added.
9
7
  Review the following changes before updating the package pin.
@@ -0,0 +1,74 @@
1
+ # Migrate before past-layout support is removed
2
+
3
+ Use this guide before upgrading to the release that removes the pre-0.29
4
+ storage and OAuth layout migrations. [Deployment upgrades](./deploying.md#upgrade-an-existing-deployment)
5
+ cover the general procedure; [the agent index](./README.md) routes other work.
6
+ Apply intervening configuration and provider migrations too.
7
+
8
+ **0.37.1 is the last bridge release containing these migrations.** A deployment
9
+ with Workers KV, a JSON state file, or OAuth layout-2 grants must first upgrade
10
+ to exactly `@zackbart/connecta@0.37.1` and finish the relevant migrations there.
11
+ Installing the bridge release alone does not migrate unused grants or storage.
12
+ Deployments already using D1 or SQLite with layout-3 grants need no conversion.
13
+ Keep the existing database, connector ids, owner partitions, and vault key.
14
+
15
+ ## Before updating the package pin
16
+
17
+ 1. Back up the source state and destination database securely, including expiry
18
+ metadata, and preserve the credential encryption key. Stop traffic and all
19
+ background writers; drain OAuth callbacks and refreshes. Keep a recoverable
20
+ 0.37.1 deployment and its installed package until verification completes.
21
+ 2. For Workers KV, use 0.37.1's installed
22
+ `examples/worker/scripts/copy-kv-to-d1.mjs` and `kv-to-d1.wrangler.jsonc`.
23
+ Follow that version's `examples/worker/README.md#upgrading-from-028`:
24
+ wait for stable KV, run `--maintenance`, resolve invalid entries and
25
+ conflicts, run `--maintenance --verify`, switch to D1 under maintenance,
26
+ verify, then run `--maintenance --mark-live` before reopening traffic.
27
+ The underlying API is `copyKvToD1(kv, db, { source })` from
28
+ `@zackbart/connecta/d1`; finish every returned cursor, verify hashes and
29
+ expiries, and call `markKvToD1Live(db, source)` before cutover. Never copy
30
+ stale KV over a database that has accepted new writes.
31
+ 3. For Node's pre-SQLite JSON state, stop the server and run the bridge CLI:
32
+
33
+ ```sh
34
+ npx --yes --package=@zackbart/connecta@0.37.1 connecta migrate-state .connecta-state.json .connecta.sqlite
35
+ ```
36
+
37
+ It copies live entries with their expiry, keeps existing destination keys,
38
+ and leaves the JSON file unchanged. The old activity JSONL is not imported.
39
+ Use the destination SQLite file for subsequent starts.
40
+
41
+ 4. While still running 0.37.1 over the SQL destination, open **every OAuth
42
+ grant once, for every connector and owner partition** through its normal
43
+ authorized connection. This includes dormant personal grants. The first
44
+ grant read converts layout 2 to the single layout-3 `oauth:grant` record
45
+ and deletes historical keys. Merely listing configuration is insufficient.
46
+ Grants too old to have issuer binding, invalid ciphertext, and pending
47
+ consents require fresh authorization on the bridge release.
48
+ 5. Verify each existing OAuth connection, vault credential and agent token,
49
+ including every personal owner. Confirm layout-3 grant records and no
50
+ pending layout-2 cleanup using trusted storage tooling without printing
51
+ credential bodies. Only then upgrade the package pin to the removing release.
52
+
53
+ ## Removed interfaces and stale state
54
+
55
+ | Removed path | Behavior after upgrading | Recovery |
56
+ | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
57
+ | OAuth layout-2 reader and cleanup | An owner with only old keys has no usable grant. Reads return absent, credentials are never opened or copied, and a warning says to authorize again or migrate on 0.37.1. Calls require consent. Old keys remain untouched. Existing layout-3 grants, including those with an obsolete cleanup marker, remain readable. | Connect again. To preserve an old grant instead, restore a consistent pre-upgrade backup and run the bridge procedure. |
58
+ | `copyKvToD1`, `markKvToD1Live`, their types/error, and copy script/config | Named imports fail; no KV copy runs. A KV adapter without atomic compare-and-set is refused at construction. A fresh D1 database contains none of the old credentials or tokens. The `/d1` subpath still exports `d1Storage` and `d1ActivityStore`. | Stop writers and restore a consistent backup with 0.37.1, then copy and verify before cutover. |
59
+ | `importStateFile`, `StateFileImport`, and `connecta migrate-state` | Named imports fail; the CLI command exits nonzero with usage. The SQLite adapter never reads the JSON file, so a fresh database has no old credentials or tokens. | Import on 0.37.1 while stopped, then point the deployment at that SQLite file. |
60
+ | Retired `execute.resumableWrites`, `execute.pausedRunTtlSeconds`, `identity`, `grant`, and deployment/pool `trust` migration hints | Construction still rejects these as ordinary unknown configuration options. It no longer expands identity keys or prints replacement instructions. Pool `grant` is also rejected. | Remove obsolete options. Follow [migration to 0.33](./migration-0.33.md) for `maintainers`, pool `members`, `agents`, and explicit `readOnly`. |
61
+
62
+ A rollback after accepting new SQL writes can resurrect revoked credentials or
63
+ spent refresh tokens. Recover from a consistent backup under maintenance rather
64
+ than merging old KV/JSON state into a live database. If preserving old auth is
65
+ unnecessary, reconnect credentials and issue fresh agent tokens in the current
66
+ SQL deployment; revoke superseded credentials at their providers.
67
+
68
+ ## Verify
69
+
70
+ Run `connecta doctor --pool <pool>` with each agent's token. Open each shared
71
+ and personal OAuth connection and make a controlled read. Confirm authorization
72
+ works without an unsupported-layout warning, the intended SQL database is used,
73
+ and the operator UI shows expected credentials and activity. Remove one-shot
74
+ migration routes and bindings after successful cutover.
@@ -26,22 +26,15 @@ last seen are fixed. The restricted state is the member fixture from
26
26
  use its maintainer fixture, which covers every runs-as kind and agent pools,
27
27
  with `test/fixtures/operator-console.ts` crowding the team pool so its avatar
28
28
  stack collapses to "+3".
29
- Collections use their corresponding browser types.
30
- `test/operator-visual-fixtures.test.ts` validates contract versions, connector
31
- IDs, granted tools, matrix cells, classification, provenance, and secret
32
- exclusion on Node and Workers, and runs `expectMemberViewWithholds` on the
33
- member body. A fixture's config cannot silently become a stale copy of the
34
- server serializer.
29
+ Collections use their corresponding browser types. Real contract serialization,
30
+ member projection and secret withholding are exercised through
31
+ `test/operator-contract.test.ts` and `test/operator-contract-server.test.ts`.
35
32
 
36
33
  `test/browser/operator-visual.spec.ts` intercepts API reads and serves the real
37
- hashed assets and HTML with the production CSP. Loading responses wait on an
38
- explicit gate. Error responses use fixed HTTP failures. The map trace focuses its
39
- node instead of hovering it: the capture scrolls to the top first, which would
40
- move the node out from under a pointer and drop the highlight, so the test waits
41
- for `.map-svg.tracing` before capturing. Screenshots use a fixed
42
- clock, UTC, en-US, locally hosted fonts, disabled animations, hidden carets,
43
- and a 1280 × 900 viewport. Narrow fixtures use 390 × 844. Every test waits for
44
- its state and fonts before capturing.
34
+ hashed assets and HTML with the production CSP. It captures populated Overview
35
+ and connector Connection pages in light and dark themes: four screenshots.
36
+ Each capture waits for the heading, page content and fonts, with a fixed clock,
37
+ and resets scrolling before the full-page image.
45
38
 
46
39
  ## Loading and recovery probes
47
40
 
@@ -52,115 +45,22 @@ The suite also checks default v2 compatibility, the unchanged member projection,
52
45
  blocked custom connectors and bounded essential token-slot failure.
53
46
  `test/ui.test.ts` checks complete detail schemas and independent sibling scope cleanup.
54
47
 
55
- `test/oauth-stored-observation.test.ts` covers absent, disconnected, tokenless,
56
- sealed/unreadable and issuer-mismatched grants, owner isolation, both built-in
57
- connector paths and custom connectors. Storage spies require zero auth mutations,
58
- including migration and resealing. `test/operator-store.test.ts` counts scoped
59
- refresh/focus/mutation/poll requests, coalescing and bounded retries, and verifies
60
- stale admission blocks privileged reads, connection writes and token actions while
48
+ `test/operator-store.test.ts` counts scoped refresh/focus/mutation/poll requests,
49
+ coalescing and bounded retries, and verifies stale admission blocks privileged reads, connection writes and token actions while
61
50
  retaining the snapshot. Late reads, role/identity changes and concurrent polls
62
51
  exercise publication fences. Browser recovery and flow suites use real routes to
63
52
  check a usable shell with a stalled connector, OAuth return and scoped Refresh.
64
53
 
65
- ## Page and state matrix
66
-
67
- Each row runs empty, loading, error, populated, and restricted-viewer fixtures
68
- in both light and dark themes, for 90 screenshots. The restricted viewer is a
69
- pool member, who gets the member page, with no tabs, on every path.
70
-
71
- | Page or tab | Empty state | Loading/error request | Restricted viewer (member) |
72
- | -------------------- | ------------------------------------ | --------------------- | ----------------------------------- |
73
- | Overview | No connectors: nothing to map | Config | Member page at `/` |
74
- | Endpoints | Root endpoint without tools | Config | Member page: endpoints, accounts |
75
- | Connectors | No connectors | Config | Member page, no connector request |
76
- | Connector Tools | Empty catalog | Config | Member page, no connector request |
77
- | Connector Connection | Deployment-managed auth | Config | Member page, no connector request |
78
- | Connector Activity | No calls | Activity | Member page, no activity request |
79
- | Tokens | No declared agents | Token list | Member page, no token request |
80
- | Activity | No calls | Activity | Member page, no activity request |
81
- | Settings | Snapshot without connectors or pools | Config | Member page, no configuration facts |
82
-
83
- Populated Overview has a failing connector, auth and credential problems
84
- and a tokenless agent in its attention list. Populated Endpoints shows who can use each endpoint; populated Tokens has one
85
- agent per slot state, with pools and last seen.
86
-
87
- Another 60 screenshots cover the Overview map on the frozen v2 maintainer, one
88
- person's trace, and the narrow map list; configured, mismatched, unreadable and multifield
89
- credentials; all three OAuth client mechanisms; clean and unobserved drift;
90
- historical Activity; client setup; schema dialog; read/write filters; narrow
91
- Settings; narrow sign-in and Connection; deployment branding; `/mcp`
92
- and an agent pool expanded with every runs-as kind; command search; narrow
93
- endpoints; the connector × endpoint matrix, one cell's open popover, and the
94
- narrow matrix; a new token's one-time secret dialog; and the member page, wide
95
- and narrow. `endpoints-expanded` and `narrow-endpoints` include the team row
96
- collapsed to "+3". The base
97
- populated Activity fixture includes grouped calls, an ungrouped legacy row,
98
- classification/result size/client facts, and a catalog-change event.
99
-
100
- `test/browser/operator-matrix.spec.ts` serves the frozen v2 fixtures to the
101
- real shell. It covers the matrix's table semantics, cell names, status dots,
102
- runs-as labels in each kind's popover, popover keyboard behavior, placement at a short viewport, the in-flow
103
- fallback without CSS anchors, and the absence of `style` attributes, agent URLs on Endpoints, the member page (its
104
- received body checked with `expectMemberViewWithholds`, `/ui/data` answering 404
105
- and never requested, no maintainer fact rendered, no maintainer request sent),
106
- the 401 sign-in and 404 no-access gates on `/ui/api/config` with no maintainer
107
- navigation, the shared recovery banner on Tokens and Activity through a failed
108
- refresh that stalls past its deadline (one focusable Retry, no maintainer
109
- request until Retry succeeds), an open client setup drawer closed by a failed
110
- refresh with focus on Retry, Tokens under recovery (an open rotate question
111
- closes with focus on Retry and nothing sent; an unseen secret dialog stays open
112
- over the banner until dismissed), payload sentinels, CSP, and the refusal of a v1 body. Matrix coverage excludes retired grants from
113
- its live counts and pie, keeps their names inspectable in the popover, and
114
- renders an unavailable catalog as a dashed empty ring with "?" and an unknown
115
- accessible name. Cell names distinguish equal grants against different live
116
- catalog sizes. `test/operator-endpoints.test.ts` covers those view-model cases,
117
- including a known empty catalog versus an unavailable one.
118
- `test/operator-connection-map.test.ts` also checks that a failed or unobserved
119
- catalog counts no tools, which the map draws as a muted dash, while a known
120
- empty catalog counts zero.
121
- `test/browser/operator-overview.spec.ts` covers the Overview on the frozen v2
122
- fixtures: the status pill, stat labels and numbers, map columns, dashed read-only grants and dotted
123
- tokenless access; attention rows with their fix links, a copied fix prompt equal
124
- to the catalogue's text, config order through a staggered full refresh, prototype-named
125
- connector IDs during loading and failure, and stable single-card height when
126
- its catalog empties. A single long-id, long-title card at 320, 390, 1024 and
127
- 1440px covers all eight status labels, both auth scopes, with and without the
128
- Read-only badge, tools and an action. Text rows stay single-line, full text
129
- remains accessible, links stay focusable, and the detail header and Overview
130
- attention rows retain their height; the hover
131
- sentence replacing the legend, and dimming; keyboard focus in column order with each node's sentence
132
- as its accessible name, Enter opening an endpoint's row and a connector; the
133
- narrow list, whose caller chips link where their map nodes do; an empty deployment; and a member at `/` getting the member page
134
- with no maintainer read, plus CSP and no `style` attributes.
135
- `test/browser/operator-console.spec.ts` covers UI-3: who-can-use chips by
136
- label, raw id and agent mark and "+N" from the keyboard; Tokens rows,
137
- issue with the once-only secret dialog, in-row rotate and revoke questions,
138
- 503, 499 and 409 failures that send exactly one request, slots missing from
139
- the list or left unresolved shown with disabled controls until Refresh; and the
140
- member page (its received body checked with `expectMemberViewWithholds`, no
141
- tabs, Search or maintainer fact, OAuth Connect, Reconnect and Disconnect sent as
142
- `?mode=continue`, `?mode=restart` and `DELETE`, the credential `actions`
143
- shapes, a refresh that drops an action closing its confirmation, a failed or
144
- stalled refresh keeping member chrome with Retry, a consent that outlasts the
145
- OAuth poll window), plus keyboard, sentinels, CSP and no `style` attributes.
146
- `test/operator-console.test.ts` covers the chip, slot-row and member-page view
147
- models. `test/browser/operator-scheme.spec.ts` holds the main bundle and checks the
148
- first painted background: saved dark on a light system paints dark, a pinned
149
- light deployment paints light over saved dark, and throwing storage keeps the
150
- system scheme while the released bundle settles on the normal bearer gate, and a
151
- sign-in there raises no error. The real-route token test in `test/browser/operator-ui.spec.ts` serves
152
- the contract, `/ui/data` and the slot routes from one real v2 deployment and
153
- checks that each mutation sent a distinct 22-character `expect`.
154
- `test/operator-store.test.ts` serves `/ui/api/config` from its own mock, so
155
- each test's data and detail answers stay separate, and covers role changes: a
156
- maintainer demoted after a failed refresh keeps no maintainer state and sends
157
- no maintainer request, and a promoted member loads maintainer data fresh. It
158
- also drives UI-3's slot fence with a session-token read held open: reloads and
159
- contract refreshes that move or drop a slot before dispatch, late results that
160
- cannot overwrite newer evidence, unknown and unreadable outcomes that only a
161
- later list read settles, revisions sent as `expect` and compared with the
162
- contract, an identity change that leaves the next identity's fence alone, and
163
- member actions whose `manage` a refresh changes.
54
+ ## Browser behavior evidence
55
+
56
+ | Suite | Assertions |
57
+ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
58
+ | `test/browser/operator-matrix.spec.ts` | Members see their own page on every path, get scoped setup links, and never request maintainer data. |
59
+ | `test/browser/operator-overview.spec.ts` | Overview health, counts and map edges; per-caller status and principal-refusal copy without secret fix prompts. |
60
+ | `test/browser/operator-console.spec.ts` | Token issue/rotate/revoke confirmations and once-only secret display; member credential fields and OAuth connect/reconnect/disconnect controls. |
61
+ | `test/browser/operator-pages.spec.ts` | Resolved read/write filters, inert schema text, Activity history/grouping, and legacy URL redirects. |
62
+ | `test/browser/operator-shell.spec.ts` | Clerk loader and child-script behavior under CSP, with inline and foreign scripts blocked. |
63
+ | `test/browser/operator-ui.spec.ts` | Identity changes cancel reads and close popups, OAuth polling stays scoped, token mutations use real routes and distinct revisions, and declared agents show scoped credentials and usage. |
164
64
 
165
65
  Screenshots cover presentation. Keep unit and server tests for INV-6 sentinels,
166
66
  secret disclosure, auth and grant boundaries, CSRF, identity fences, cancellation,
@@ -699,10 +699,9 @@ the page's styles.
699
699
 
700
700
  `src/operator-ui/config-summary.ts` maps the snapshot and its provenance to
701
701
  those tiles: one table of limit labels, the formatters, and the walk that turns
702
- an unmapped key into an Other tile. `app/config-tiles.tsx` draws them, and
703
- `test/operator-config-summary.test.ts` checks formatting, provenance, unknown
704
- keys, an empty deployment, and that a real deployment's snapshot leaves no key
705
- unmapped.
702
+ an unmapped key into an Other tile. `app/config-tiles.tsx` draws them.
703
+ `test/browser/operator-flows.spec.ts` checks Settings provenance through the
704
+ production UI and real routes.
706
705
 
707
706
  The contract type is [contract.ts](https://github.com/zackbart/connecta/blob/main/src/operator-ui/contract.ts).
708
707
  [UI routes](https://github.com/zackbart/connecta/blob/main/src/routes/ui.ts) and
@@ -1,15 +1,9 @@
1
1
  # Provider auth migration
2
2
 
3
- Hosted selections described in this historical migration are now removed.
4
- For Stripe, Vercel, Cloudflare, Notion, Mixpanel, and GitHub hosted connections,
5
- use the [current hosted MCP migration guide](./hosted-mcp-migration.md).
6
- The API migrations below remain applicable.
7
-
8
- Use this upgrade guide when moving a Stripe, Vercel, or Cloudflare
9
- deployment from 0.30 to 0.31, where `auth` selects each provider's
10
- implementation.
11
- [Deployment upgrades](./deploying.md#upgrade-an-existing-deployment) cover other
12
- version changes; [integrating services](./integrating.md) covers new connectors.
3
+ This guide covers the 0.30-to-0.31 change to auth-selected implementations.
4
+ For current versions, follow [deployment upgrades](./deploying.md#upgrade-an-existing-deployment)
5
+ and [hosted MCP migration](./hosted-mcp-migration.md); hosted selectors below
6
+ are historical.
13
7
 
14
8
  A dual provider requires `auth`. `{ type: "oauth" }` connects the vendor's
15
9
  hosted MCP server, OAuth only. A key type connects Connecta's REST connector
@@ -1,20 +1,9 @@
1
1
  # Notion, Vercel and Cloudflare migration for 0.29
2
2
 
3
- Hosted selections described in this historical migration are now removed.
4
- For Stripe, Vercel, Cloudflare, Notion, Mixpanel, and GitHub hosted connections,
5
- use the [current hosted MCP migration guide](./hosted-mcp-migration.md).
6
- The API migrations below remain applicable.
7
-
8
- Use this upgrade guide for an existing deployment.
9
- [Deployment upgrades](./deploying.md#upgrade-an-existing-deployment) cover other
10
- version changes; [integrating services](./integrating.md) covers new connectors.
11
- [The agent index](./README.md) routes package maintenance separately.
12
-
13
- This was the Phase 1 item 5d migration input for [Phase 5 release #709](https://github.com/zackbart/connecta/issues/709),
14
- which shipped as 0.29.0.
15
- Deployments that use Notion or Cloudflare must check their actual grants and
16
- connector ids in deployment configuration before that release.
17
- The provider audit establishes available auth modes, not production OAuth grants.
3
+ This guide records the 0.29 Notion, Vercel and Cloudflare option changes.
4
+ For upgrades to current versions, use [deployment upgrades](./deploying.md#upgrade-an-existing-deployment)
5
+ and [hosted MCP migration](./hosted-mcp-migration.md); the hosted selectors below
6
+ are historical and cannot be used in current configuration.
18
7
 
19
8
  Cloudflare's part of this guide is superseded: `cloudflare()` now selects its
20
9
  implementation by `auth` and its key connector is complete on its own. Follow
@@ -67,12 +67,10 @@ tokens, upgrading, and diagnosis with `connecta doctor` to their procedures.
67
67
  - All state lives in the one D1 database bound as `CONNECTA_DB`, through
68
68
  `d1Storage` (and `d1ActivityStore`) from `@zackbart/connecta/d1`. Do not add
69
69
  a KV namespace, a second database, or a copied storage adapter; connecta
70
- creates its own tables. The only KV binding is in `kv-to-d1.wrangler.jsonc`,
71
- which is never deployed. It exists for the one-shot copy from a 0.28 Workers
72
- KV deployment (README.md § "Upgrading from 0.28"). Back up, block traffic
73
- and background writers, drain, wait for stable KV, copy and verify, deploy
74
- while maintenance remains, then mark cutover before reopening traffic. Never
75
- rerun stale KV after cutover. Retain backups before removing KV.
70
+ creates its own tables. Pre-0.29 Workers KV state must be copied on
71
+ Connecta 0.37.1 before upgrading past that bridge release; follow the installed
72
+ package's `documentation/migration-retired-layouts.md`. The current example
73
+ includes no KV copy script or binding.
76
74
  - Add application logic only inside deliberate `api()` connector handlers.
77
75
  Do not copy or modify Connecta package internals here.
78
76
  - Prefer `api()` when the agent must see an exact reviewed capability set;
@@ -21,14 +21,13 @@ migrations, and secrets.
21
21
 
22
22
  ## Files
23
23
 
24
- | File | What it is |
25
- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
26
- | `src/index.ts` | the Worker entrypoint — starts the configuration, under 30 lines |
27
- | `src/connecta.config.ts` | connectors, auth, storage, and optional modules, as `defineConfig((env) => …)` |
28
- | `alchemy.run.ts` | the deployment: Worker, vars, secrets, D1, Worker Loader, and both Access applications |
29
- | `wrangler.jsonc` | local `wrangler dev` only, with a simulated Access identity; never used to deploy |
30
- | `gitignore` | the copied deployment's `.gitignore`, shipped under this name because npm strips `.gitignore` ([Copied into its own repository](#copied-into-its-own-repository)) |
31
- | `scripts/copy-kv-to-d1.mjs`, `kv-to-d1.wrangler.jsonc` | one-shot copy of a 0.28 Workers KV deployment's state into D1, run once and deleted ([Upgrading from 0.28](#upgrading-from-028)) |
24
+ | File | What it is |
25
+ | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
26
+ | `src/index.ts` | the Worker entrypoint — starts the configuration, under 30 lines |
27
+ | `src/connecta.config.ts` | connectors, auth, storage, and optional modules, as `defineConfig((env) => …)` |
28
+ | `alchemy.run.ts` | the deployment: Worker, vars, secrets, D1, Worker Loader, and both Access applications |
29
+ | `wrangler.jsonc` | local `wrangler dev` only, with a simulated Access identity; never used to deploy |
30
+ | `gitignore` | the copied deployment's `.gitignore`, shipped under this name because npm strips `.gitignore` ([Copied into its own repository](#copied-into-its-own-repository)) |
32
31
 
33
32
  Construct Connecta once per isolate and pass `ctx` through to `fetch`, as the
34
33
  example entrypoint does.
@@ -261,31 +260,10 @@ the Access policy or application.
261
260
 
262
261
  ### Let agents through Access
263
262
 
264
- `ConnectaAgents` in `alchemy.run.ts` is a second self-hosted Access
265
- application whose destination is `<PUBLIC_URL host>/agent/*`, with a single
266
- policy whose action is **Bypass** and whose include rule is **Everyone**. The
267
- Worker-level application still protects every other path. Never bypass any
268
- other path. To serve agents on another hostname too, add a destination for it,
269
- for example `{ type: "public", uri: "agents.example.com/agent/*" }`. Through the
270
- Access API, the application is:
271
-
272
- ```json
273
- {
274
- "type": "self_hosted",
275
- "name": "connecta agents",
276
- "destinations": [{ "type": "public", "uri": "connecta.example.com/agent/*" }],
277
- "policies": [{ "name": "agents bypass", "decision": "bypass", "include": [{ "everyone": {} }] }]
278
- }
279
- ```
280
-
281
- It must be a hostname-and-path (`public`) destination: a second Worker
282
- destination is refused because the Worker-level application owns it. Changes
283
- took 15–19 seconds to settle when probed, occasionally longer, with transient
284
- edge errors meanwhile. Do not rely on a fixed wait; repeat
285
- [Verify after deploying](#verify-after-deploying). Connecta ignores Access
286
- context on `/agent/*` and refuses every other spelling of that namespace before
287
- auth. [Deploying Connecta](https://github.com/zackbart/connecta/blob/main/documentation/deploying.md#agent-endpoints-behind-cloudflare-access)
288
- records the untested cases and the propagation details.
263
+ `ConnectaAgents` in `alchemy.run.ts` declares the agent bypass. Follow
264
+ [Agent endpoints behind Cloudflare Access](https://github.com/zackbart/connecta/blob/main/documentation/deploying.md#agent-endpoints-behind-cloudflare-access)
265
+ for the hostname-and-path application, API JSON, matching rules and controls.
266
+ Repeat [Verify after deploying](#verify-after-deploying) after Access changes.
289
267
 
290
268
  ### Moving a Wrangler-deployed Worker to Alchemy
291
269
 
@@ -357,7 +335,7 @@ it reports, run Alchemy and Wrangler only on a trusted machine, keep
357
335
  `alchemy dev` and `wrangler dev` bound to localhost, and give the API token
358
336
  only the four permissions in [Deploy](#deploy) and a short expiry.
359
337
 
360
- `wrangler` serves only `wrangler dev` and `scripts/copy-kv-to-d1.mjs`. A
338
+ `wrangler` serves local `wrangler dev`. A
361
339
  `tsconfig.json` like the following lets `tsc --noEmit`
362
340
  resolve `D1Database`, `WorkerLoader`, and `ExecutionContext`, and checks the
363
341
  stack:
@@ -623,87 +601,14 @@ Each shape moves to the one `CONNECTA_DB` binding:
623
601
 
624
602
  #### Copying Workers KV state into D1
625
603
 
626
- Storage keys did not change in 0.29. `copyKvToD1(kv, db, { source })` from
627
- `@zackbart/connecta/d1` preserves live keys, exact values including vault
628
- ciphertext, and absolute expiries. The source is the KV namespace id. Counts
629
- and failures name only families, never keys or values. Oversized UTF-8 strings
630
- or rows are skipped and counted as invalid against D1's
631
- [2,000,000-byte limit](https://developers.cloudflare.com/d1/platform/limits/).
632
- A different live D1 value or expiry is a conflict, kept by default.
633
-
634
- Use a maintenance window. Copying while either deployment serves can restore
635
- revoked tokens, stale refresh tokens, or disconnected connectors. A rerun is
636
- safe only while the source remains stable and D1 has no new application writes.
637
- The script reads the source id from `kv-to-d1.wrangler.jsonc` and checks two
638
- consecutive listing/hash passes before a copy or verification pass. The config
639
- uses remote KV and D1 bindings and is never deployed.
640
-
641
- Prepare the new configuration without deploying it. Use the existing activity
642
- D1 database as `CONNECTA_DB`, keeping its name and id; otherwise create one
643
- with `wrangler d1 create connecta`. Remove `kv_namespaces` and copied adapters.
644
- Configuration lives in `src/connecta.config.ts` and
645
- `src/index.ts` is the entry point. Set the plain var `CONNECTA_ACTIVITY = "on"`
646
- so preserved activity remains visible. Bind only `CONNECTA_DB` and `LOADER` for storage/execution;
647
- keep existing auth vars and the credential secret.
648
- Fill in the copy config's namespace id and the same D1 database name/id,
649
- then `wrangler login` and check the prepared deployment with a dry run.
650
-
651
- 1. Back up KV with a bulk export including values and expiration metadata.
652
- Export D1 with `wrangler d1 export <db> --remote --output before-cutover.sql`.
653
- Store backups securely and preserve the exact credential encryption key,
654
- whatever secret name the deployment stores it under.
655
- 2. Block traffic using maintenance mode or turn the route off. Stop cron,
656
- queue consumers, scheduled jobs, and every other KV/D1 writer. Drain all
657
- in-flight requests, including OAuth callbacks and token refreshes.
658
- 3. Wait at least **60 seconds after the last write**, or the longest configured
659
- KV `cacheTtl`, whichever is greater. KV propagation can take longer, so this
660
- is a minimum, not proof of consistency. See
661
- [KV consistency](https://developers.cloudflare.com/kv/concepts/how-kv-works/).
662
- Confirm a stable source with two consecutive listing/hash passes that match;
663
- the script performs this check. If they differ, stay in maintenance, wait
664
- longer, and repeat. Expiring entries may also require another pass.
665
- 4. Copy **before switching traffic** with
666
- `node scripts/copy-kv-to-d1.mjs --maintenance`. Resolve all `invalid` and
667
- `conflicts` counts under maintenance; either makes the script exit non-zero.
668
- An oversized entry requires a deliberate per-family remediation, not a
669
- retry of the same value. Overwrite only families explicitly reviewed as
670
- stale in D1, for example `--maintenance --overwrite-family catalog`.
671
- Token/OAuth/vault families require the operator to confirm D1 rows are stale
672
- and also pass `--confirm-stale-d1`; never infer this from a conflict alone.
673
- There is no blanket `--overwrite`. Then run
674
- `node scripts/copy-kv-to-d1.mjs --maintenance --verify`. It compares SHA-256
675
- hashes of exact values and absolute expiries for live source keys, reports
676
- `verified` / `mismatches` counts by family only, and exits non-zero on any
677
- invalid entry or mismatch. Keep traffic and writers stopped until these
678
- counts are resolved. A verification pass does not rewrite copied entries.
679
- 5. Deploy the D1 configuration with the deployment's `wrangler deploy` while maintenance remains.
680
- Run `connecta doctor --pool <pool>` using Access service credentials plus a
681
- stored `cta_` bearer through `CONNECTA_TOKEN`. Verify an existing
682
- OAuth connector without re-consent, an existing `cta_` token, a connector
683
- using a vault credential, and prior activity in the Activity view. Run
684
- these controlled checks with other traffic and background writers blocked.
685
- 6. Seal the source with
686
- `node scripts/copy-kv-to-d1.mjs --maintenance --mark-live`, then reopen
687
- traffic and background writers. The permanent D1 marker refuses later
688
- copies. Never rerun after traffic resumes. `--i-know-this-is-stale` is only
689
- an emergency override after stopping writers again and assessing stale KV;
690
- it does not make stale tokens or credentials safe to restore.
691
- Retain backups before deleting the KV namespace. After a clean observation
692
- period, remove the copy script/config and delete KV with
693
- `wrangler kv namespace delete --namespace-id <id>`.
694
-
695
- An in-Worker copy can call
696
- `copyKvToD1(env.CONNECTA_KV, env.CONNECTA_DB, { source: namespaceId, cursor })`
697
- from a guarded one-off route under the same maintenance procedure. Each call
698
- reads at most `maxKeys` keys, default 500. For near-limit rows use 200 or fewer
699
- so additional byte-bounded D1 batches fit the invocation's query budget.
700
- Loop until `done`, passing each returned cursor. Tokens keep KV's raw cursor
701
- in D1 for seven days, are bound to the source id, and are atomically consumed.
702
- Unknown, spent, or foreign-source tokens are refused without echoing them.
703
- On failure, use the error's replacement token or restart under maintenance.
704
- Call `markKvToD1Live(db, namespaceId)` before reopening traffic, and remove the
705
- route and KV binding. The source stability check is the operator's duty when
706
- using the API directly. Remote bindings remain unverified until deploy day.
604
+ Complete this conversion on Connecta 0.37.1 before installing the release
605
+ that removes migrations. The current `/d1` subpath provides `d1Storage` and
606
+ `d1ActivityStore`; it no longer exports `copyKvToD1`, `markKvToD1Live`, or
607
+ migration types, and this example no longer includes the copy script/config.
608
+ Use the 0.37.1 package's Worker example under maintenance, verify the copy,
609
+ mark cutover, and open every owner's OAuth grant on that bridge release.
610
+ Follow [Retired layout migrations](../../documentation/migration-retired-layouts.md)
611
+ for the required order and recovery. Never copy stale KV into a live database.
707
612
 
708
613
  ## Activity history (optional)
709
614
 
@@ -68,14 +68,11 @@ sequenceDiagram
68
68
  C-->>H: Serve the pool's permitted tools
69
69
  ```
70
70
 
71
- Anyone who obtains either token can act as the agent. Trust the Vercel
72
- project code and build steps that can obtain its tokens, and enable only
73
- environments that should have the pool's access.
74
-
75
- The [token management guide](../documentation/auth.md#issue-rotate-or-revoke-an-agent-token)
71
+ [Safety and trust](./safety-and-trust.md#a-credential-proves-an-agent-not-a-person)
72
+ explains who can act with these credentials. The
73
+ [token management guide](../documentation/auth.md#issue-rotate-or-revoke-an-agent-token)
76
74
  and [Vercel identity guide](../documentation/auth.md#vercel-workload-credentials)
77
- own availability, setup, rotation, and revocation. If both methods are
78
- enabled, stopping one does not stop the other.
75
+ own setup, rotation, and revocation.
79
76
 
80
77
  ## An optional integration for Eve
81
78
 
@@ -114,29 +111,9 @@ identity. Instructions help the model use tools; they grant no permissions.
114
111
 
115
112
  ## Decide whether writes need a person
116
113
 
117
- The helper defaults to unattended execution of authorized writes. Connecting
118
- an agent does not automatically add an approval step.
119
-
120
- ```mermaid
121
- flowchart TB
122
- Call["Agent requests a change"] --> Ask{"App asks for approval?"}
123
- Ask -->|Yes| Approved{"Person approves?"}
124
- Approved -->|No| Stop["Stop"]
125
- Approved -->|Yes| Pool{"Connecta allows this write?"}
126
- Ask -->|No| Pool
127
- Pool -->|No| Refuse["Refuse before sending"]
128
- Pool -->|Yes| Send["Send the change"]
129
- ```
130
-
131
- For an interactive Eve agent, `gateWrites: true` asks before tools not marked
132
- read-only. An explicit Eve approval policy takes precedence. If the agent
133
- must never update data, use a read-only pool.
134
-
135
- Approval may rely on an earlier tool label. A writable pool can execute a
136
- newly classified write without a fresh approval; a read-only pool refuses it.
137
- [Safety and trust](./safety-and-trust.md) explains the boundary, and the
138
- [helper guide](https://github.com/zackbart/connecta/blob/main/packages/connecta-eve/README.md#approval-and-writes)
139
- explains the policy mechanics.
114
+ Agree on an approval policy before enabling writes. See
115
+ [approval boundaries](./safety-and-trust.md#read-only-blocks-actions-that-change-data)
116
+ and the [Eve helper's approval setup](https://github.com/zackbart/connecta/blob/main/packages/connecta-eve/README.md#approval-and-writes).
140
117
 
141
118
  ## When accounts or audiences differ
142
119
 
@@ -115,8 +115,8 @@ unbounded data.
115
115
 
116
116
  With meta-tools, one discovered read can use a direct call. Finding an unfamiliar
117
117
  action, combining several calls, or reducing a large answer belongs in a program.
118
- On a writable endpoint, a program may also change data. The AI app decides
119
- whether to ask for approval before running it.
118
+ On a writable endpoint, a program may also change data; see
119
+ [approval boundaries](./safety-and-trust.md#read-only-blocks-actions-that-change-data).
120
120
 
121
121
  The [endpoint workflow](../documentation/operating.md) and
122
122
  [code reference](../documentation/code-mode.md) explain the mechanics.
@@ -71,7 +71,10 @@ or contradictory read hints count as writes, but a service can mislabel an
71
71
  action and an operator can override its label. Use restricted service
72
72
  credentials as another boundary where possible.
73
73
 
74
- The AI app owns approvals. It may ask based on an earlier tool label. If a
74
+ The Eve helper defaults to unattended authorized writes. For interactive use,
75
+ `gateWrites: true` asks before tools not marked read-only; an explicit Eve
76
+ approval policy takes precedence. The AI app owns approvals. It may ask based
77
+ on an earlier tool label. If a
75
78
  read becomes a write, a writable pool can execute it without a fresh
76
79
  approval; a read-only pool refuses it. Connecta does not pause a program to
77
80
  ask a person partway through.