@zackbart/connecta 0.32.0 → 0.33.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.
- package/CHANGELOG.md +63 -0
- package/README.md +15 -7
- package/bin/connecta.mjs +24 -6
- package/bin/version.mjs +1 -1
- package/dist/access-tokens.d.ts +167 -23
- package/dist/access-tokens.js +676 -140
- package/dist/agent-identity.js +47 -0
- package/dist/auth/cloudflare-access.js +13 -5
- package/dist/call-admission-context.js +15 -0
- package/dist/call-admission.js +30 -43
- package/dist/call-recovery.js +6 -2
- package/dist/config-value-sources.js +11 -9
- package/dist/config.d.ts +37 -75
- package/dist/config.js +110 -36
- package/dist/connector-access.d.ts +4 -34
- package/dist/connector-access.js +15 -99
- package/dist/connector-caller.d.ts +7 -1
- package/dist/connector-caller.js +3 -2
- package/dist/connectors/api-connector.d.ts +27 -4
- package/dist/connectors/api-connector.js +2 -0
- package/dist/connectors/remote-mcp.js +2 -0
- package/dist/describe-config.d.ts +29 -7
- package/dist/describe-config.js +7 -17
- package/dist/index.d.ts +4 -3
- package/dist/index.js +29 -10
- package/dist/invocation.js +5 -3
- package/dist/membership.d.ts +51 -0
- package/dist/membership.js +121 -0
- package/dist/module-contracts.d.ts +23 -6
- package/dist/operator-record.d.ts +2 -2
- package/dist/operator-record.js +2 -4
- package/dist/operator-ui/agents.d.ts +74 -0
- package/dist/operator-ui/agents.js +104 -0
- package/dist/operator-ui/contract.d.ts +149 -28
- package/dist/operator-ui/endpoints.js +192 -0
- package/dist/operator-ui/fix-prompts.js +4 -4
- package/dist/operator-ui/generated.js +5 -4
- package/dist/operator-ui/member-page.js +112 -0
- package/dist/operator-ui/model.d.ts +14 -6
- package/dist/operator-ui/view.d.ts +84 -19
- package/dist/operator-ui/view.js +82 -21
- package/dist/page-styles.js +1 -1
- package/dist/provider.d.ts +61 -8
- package/dist/provider.js +46 -7
- package/dist/providers/_shared/google/workspace.d.ts +53 -16
- package/dist/providers/_shared/google/workspace.js +30 -8
- package/dist/providers/_shared/rest/tools.js +2 -2
- package/dist/providers/_shared/rest/value-safety.d.ts +50 -0
- package/dist/providers/_shared/rest/value-safety.js +699 -7
- package/dist/providers/ccb/index.js +1 -1
- package/dist/providers/cloudflare/index.js +3 -3
- package/dist/providers/cloudflare/rest.js +25 -3
- package/dist/providers/cloudflare/skill.generated.js +1 -1
- package/dist/providers/cloudflare/value-safety.js +32 -0
- package/dist/providers/docs/index.js +3 -3
- package/dist/providers/docs/skill.generated.js +2 -2
- package/dist/providers/drive/index.js +3 -3
- package/dist/providers/drive/skill.generated.js +2 -2
- package/dist/providers/forms/index.js +3 -3
- package/dist/providers/forms/skill.generated.js +2 -2
- package/dist/providers/gmail/index.js +10 -8
- package/dist/providers/gmail/skill.generated.js +2 -2
- package/dist/providers/mixpanel/index.js +1 -1
- package/dist/providers/notion/index.d.ts +7 -0
- package/dist/providers/notion/index.js +100 -11
- package/dist/providers/notion/rest.js +45 -5
- package/dist/providers/notion/skill.generated.js +2 -2
- package/dist/providers/notion/value-safety.js +30 -5
- package/dist/providers/overflow/index.js +1 -1
- package/dist/providers/planning-center/index.js +1 -1
- package/dist/providers/sheets/index.d.ts +3 -0
- package/dist/providers/sheets/index.js +6 -3
- package/dist/providers/sheets/skill.generated.js +2 -2
- package/dist/providers/slides/index.js +3 -3
- package/dist/providers/slides/skill.generated.js +2 -2
- package/dist/providers/stripe/rest.js +9 -2
- package/dist/providers/stripe/skill.generated.js +1 -1
- package/dist/providers/stripe/value-safety.js +22 -0
- package/dist/providers/vercel/rest.js +20 -2
- package/dist/providers/vercel/skill.generated.js +1 -1
- package/dist/providers/vercel/value-safety.js +22 -0
- package/dist/registry.d.ts +2 -3
- package/dist/registry.js +8 -9
- package/dist/routes/access-tokens.js +82 -75
- package/dist/routes/activity-disclosure.js +17 -18
- package/dist/routes/activity.js +34 -54
- package/dist/routes/actor-labels.js +33 -4
- package/dist/routes/agent-path.js +43 -0
- package/dist/routes/connect.js +16 -12
- package/dist/routes/credentials.js +16 -40
- package/dist/routes/mcp.js +145 -95
- package/dist/routes/oauth-management.js +11 -5
- package/dist/routes/oauth.js +3 -9
- package/dist/routes/operator.js +24 -23
- package/dist/routes/shared.d.ts +60 -20
- package/dist/routes/shared.js +187 -96
- package/dist/routes/ui-config.js +437 -97
- package/dist/routes/ui-data.js +2 -2
- package/dist/routes/ui.js +9 -16
- package/dist/runtime/call-admission.js +9 -0
- package/dist/server.js +5 -0
- package/dist/storage/keys.js +9 -1
- package/dist/types.d.ts +11 -0
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +16 -14
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/workspace-address.js +9 -0
- package/dist/workspace-subject.js +23 -0
- package/documentation/README.md +46 -22
- package/documentation/architecture.md +355 -50
- package/documentation/auth.md +775 -243
- package/documentation/code-mode.md +14 -11
- package/documentation/deploying.md +121 -24
- package/documentation/integrating.md +92 -21
- package/documentation/meta-tools.md +14 -9
- package/documentation/migration-0.33.md +344 -0
- package/documentation/operating.md +3 -1
- package/documentation/operator-tests.md +115 -28
- package/documentation/operator-ui.md +326 -61
- package/documentation/provider-auth-migration.md +37 -23
- package/documentation/provider-migration-0.29.md +2 -2
- package/examples/worker/AGENTS.md +30 -8
- package/examples/worker/README.md +92 -53
- package/examples/worker/src/connecta.config.ts +36 -20
- package/examples/worker/wrangler.jsonc +3 -0
- package/package.json +3 -2
- package/templates/node/.env.example +3 -0
- package/templates/node/AGENTS.md +27 -6
- package/templates/node/Dockerfile +2 -2
- package/templates/node/README.md +67 -42
- package/templates/node/docker-compose.yml +3 -2
- package/templates/node/package.json +4 -3
- package/templates/node/src/adopt-token.ts +23 -0
- package/templates/node/src/connecta.config.ts +28 -12
- package/templates/node/src/rotate-token.ts +17 -0
- package/templates/node/src/provision-token.ts +0 -17
|
@@ -10,6 +10,7 @@ credential ownership, and grants use [Auth](./auth.md).
|
|
|
10
10
|
| Task | Read |
|
|
11
11
|
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
12
12
|
| Enable UI, vault, or history in a deployment | [Setup](#setup), then the platform template |
|
|
13
|
+
| Find a member's endpoint or set up their client | [Use the member page](#use-the-member-page) |
|
|
13
14
|
| Consume config, provenance, status, or activity | [Operator data contract](#operator-data-contract) |
|
|
14
15
|
| Change a UI page or data route | [Source and tests](#source-and-tests), [browser verification](./operator-tests.md) |
|
|
15
16
|
| Diagnose permission refusals | [Management permissions](./auth.md#management-permissions), [activity disclosure below](#operator-data-contract) |
|
|
@@ -22,81 +23,326 @@ and [Worker example](../examples/worker/README.md#select-optional-modules)
|
|
|
22
23
|
own the runnable configuration, variables, and branding shape. The UI is an
|
|
23
24
|
explicit optional import and stays outside the root package import graph.
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
Endpoints, Connectors, Activity, Tokens, and Settings are the maintainer's
|
|
27
|
+
pages. Endpoints is the default page at `/`: one row for `/mcp` and each pool,
|
|
28
|
+
with a copyable URL, who can use it, tool count, endpoint mode, and client
|
|
29
|
+
setup. Who can use it is `root.maintainers` on `/mcp` and the pool's `members`
|
|
30
|
+
elsewhere: a person by label, or by raw id when the label is null, beside their
|
|
31
|
+
initials, and an agent as `agent:<name>` with a token mark. A row shows four
|
|
32
|
+
and a "+N more" button that reveals the rest. A pool with
|
|
33
|
+
agent members also shows its agent URL, muted. Expanding a row lists each
|
|
34
|
+
connector on that endpoint with what it runs as and its tools, marking write
|
|
35
|
+
tools. The runs-as label comes from that endpoint's matrix cell. A shared connector
|
|
36
|
+
names its credential's source: "Shared · saved <date>" (vault), "Shared ·
|
|
37
|
+
connected <date>" (OAuth), "Shared · not configured", "Shared · set in
|
|
38
|
+
deployment", or "Shared · no credential needed"; a vault or OAuth cell without a
|
|
39
|
+
date omits it. The others read "Personal · N of M connected", "Workspace · people:
|
|
40
|
+
self · agents: <owner>" (or "none"), or "Everyone acts as <subject>" for a
|
|
41
|
+
fixed-subject Workspace connector. Connector health is not repeated per
|
|
42
|
+
endpoint: a connector that needs attention gets a status dot linking to its
|
|
43
|
+
Connection tab. Counts intersect live tools with the pool's declared tools
|
|
44
|
+
(the `/mcp` matrix cells for the root), guarded grants' live verdicts, and
|
|
45
|
+
read-only mode. Connectors lists each connector with one status badge, auth
|
|
46
|
+
scope, tool count, and last call; a problem adds one action (Connect, Replace
|
|
47
|
+
key, or Inspect) that opens Connection. A List / Matrix toggle (`?view=matrix`)
|
|
48
|
+
switches to a table of connectors by endpoint, `/mcp` first: each cell reads
|
|
49
|
+
"all", a tool count, or a dash, read-only columns are tinted, and a Runs as
|
|
50
|
+
column summarizes the `/mcp` cell, else the first pool's. A cell with tools is
|
|
51
|
+
a button named like "GitHub on /mcp/support: 1 tool, read-only"; Enter, Space or
|
|
52
|
+
a click opens a popover listing exactly that cell's tool names, write tools
|
|
53
|
+
marked, with the cell's runs-as. Escape or Tab returns focus to the cell. The
|
|
54
|
+
popover opens below its cell, or above when the viewport has more room there,
|
|
55
|
+
with a capped height that scrolls; CSS anchor positioning places it, and the
|
|
56
|
+
page sets no inline styles. A browser without anchor positioning gets the same
|
|
57
|
+
list, with the same keys, in an expansion row under the connector. `GET /ui/api/config` is the browser's one gate: a 401
|
|
58
|
+
shows sign-in, the private 404 shows a "No access" page naming who to ask, with
|
|
59
|
+
Sign out or Change token, and a 200 renders by `role`. `/ui/data`, connector
|
|
60
|
+
details, activity and tokens are requested only after the contract says
|
|
61
|
+
`maintainer`, and every such read checks the role again when it is sent, focus
|
|
62
|
+
returns included. Until a role is confirmed, the page shows its loading or
|
|
63
|
+
error state and no navigation. The store keeps the last confirmed role through
|
|
64
|
+
a failed refresh: a maintainer's page stays mounted, inert and dimmed, under
|
|
65
|
+
one shell banner with Retry, whichever page it is, and sends nothing
|
|
66
|
+
maintainer-only until a contract confirms the role again. Recovery closes the
|
|
67
|
+
page's dialogs, drawers and popovers and the command palette, and moves focus
|
|
68
|
+
to Retry. Credential and OAuth writes also wait for a contract that agrees
|
|
69
|
+
with the confirmed role: a maintainer's for a connector it shows, a member's
|
|
70
|
+
for a personal connector their contract lists with that action in `manage`;
|
|
71
|
+
otherwise the write is not sent and its row says so. An
|
|
72
|
+
answer with a different role clears everything read under the old one and
|
|
73
|
+
admits the viewer again. A
|
|
74
|
+
pool member sees the [member page](#use-the-member-page) on every path, with
|
|
75
|
+
no tabs. Connector
|
|
76
|
+
detail has Tools, Connection, and Activity tabs. Connection combines
|
|
77
|
+
authentication (including the OAuth client mechanism), catalog diagnostics,
|
|
78
|
+
one fix prompt beside each problem it reports, and the connector snapshot with its source. Settings combines inbound-auth facts with the
|
|
79
|
+
configuration snapshot and labels values as default or configured. Deployment code owns connectors, grants, pools, and classification;
|
|
29
80
|
the UI changes only authorized authentication material.
|
|
30
81
|
|
|
82
|
+
Tokens has one row per agent declared in code, in `GET /ui/access-tokens`
|
|
83
|
+
order: its pools, a state badge (No token, Issued or Revoked), the issue or
|
|
84
|
+
revoke date, and last seen ("never" when null). One line says agents are
|
|
85
|
+
declared in code; nothing creates or renames one. Issue appears for a slot with
|
|
86
|
+
no token or a revoked one, Rotate and Revoke for an issued one; rotate and
|
|
87
|
+
revoke ask first in a row under the agent's, with focus on Cancel. Every
|
|
88
|
+
mutation sends `{ "expect": "<revision>" }` with the slot revision the
|
|
89
|
+
operator confirmed against. A new secret opens once in a dialog with a copy
|
|
90
|
+
button and a note that it won't be shown again; closing it drops the secret
|
|
91
|
+
from the page, and recovery never closes it. A 409 `slot_changed` reads
|
|
92
|
+
"Changed since you looked, refresh"; a 503 `outcome_unknown` or 499 `aborted`
|
|
93
|
+
is a failure notice and is never retried. Sending a mutation leaves the slot
|
|
94
|
+
unresolved until its successful response is validated, which resolves it. Any
|
|
95
|
+
other outcome, a contract whose `agents[].token` disagrees with the list
|
|
96
|
+
(revision included) or drops the agent, or a failed read leaves it unresolved
|
|
97
|
+
until a slot-list read that started afterwards succeeds. Until then its
|
|
98
|
+
controls are off with "Refresh to continue", and each action is
|
|
99
|
+
checked again immediately before it is sent. Under the recovery banner Tokens
|
|
100
|
+
offers no Refresh of its own, and an open rotate or revoke question closes.
|
|
101
|
+
|
|
31
102
|
Install the vault for declared credential slots and activity history for
|
|
32
103
|
persisted call records. Neither module grants permission to manage or read
|
|
33
|
-
it.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
104
|
+
it: [auth](./auth.md#management-permissions) does. Interactive maintainers
|
|
105
|
+
administer shared credentials and agent tokens, maintainers read activity, and
|
|
106
|
+
pool members connect their own accounts on personal connectors in their pools.
|
|
107
|
+
Token management issues, rotates, and revokes the tokens of agents declared in
|
|
108
|
+
code; it never creates, renames, or binds an agent. Agent tokens never grant
|
|
109
|
+
interactive credential or token management authority.
|
|
110
|
+
|
|
111
|
+
## Use the member page
|
|
112
|
+
|
|
113
|
+
With `operatorUi()` enabled, sign in at the deployment's public URL using
|
|
114
|
+
Clerk (Node) or Cloudflare Access (Workers). A person listed in a pool's
|
|
115
|
+
`members` can open the page without becoming a maintainer. The page, **Your
|
|
116
|
+
connections**, has no tabs; its top bar shows branding, the signed-in account
|
|
117
|
+
(Clerk's primary email, when there is one) and Sign out or Change token. It
|
|
118
|
+
lists:
|
|
119
|
+
|
|
120
|
+
- **Your endpoints**: each admitted `/mcp/<pool>` URL with a copy button and
|
|
121
|
+
**Client setup**. For example, Bob in pool `team` copies
|
|
122
|
+
`https://connecta.example.com/mcp/team` into an MCP client and authenticates
|
|
123
|
+
as Bob.
|
|
124
|
+
- **Your accounts**: the personal connectors in their pools, each with one
|
|
125
|
+
status badge and only the controls its `manage.actions` lists. An OAuth
|
|
126
|
+
connector offers Connect, Reconnect or Disconnect; Reconnect and Disconnect
|
|
127
|
+
ask first. A credential connector offers **Add credential** when only `save`
|
|
128
|
+
is listed, and Replace, Test and Clear once a value is stored.
|
|
129
|
+
- **Shared with you**: shared connectors by name and tool count, without status.
|
|
130
|
+
|
|
131
|
+
Every browser path shows that same member page; it does not expose maintainer
|
|
132
|
+
connector-detail, activity, token, or settings pages, and it never sends a
|
|
133
|
+
maintainer request. After an action, and when the tab regains focus while an
|
|
134
|
+
authorization it started is still outstanding (up to ten minutes), it re-reads
|
|
135
|
+
`GET /ui/api/config`. Each action is checked against the current `manage`
|
|
136
|
+
again immediately before it is sent, and a refresh that drops an action closes
|
|
137
|
+
its open confirmation or form. If a refresh fails or misses its deadline, the
|
|
138
|
+
page shows its own error with Retry and moves focus to its heading; members
|
|
139
|
+
never see the maintainer recovery banner.
|
|
140
|
+
|
|
141
|
+
The page reads `GET /ui/api/config`: 200 with `role: "member"` confirms
|
|
142
|
+
membership; 401 means sign in; a private 404 means the signed-in person has
|
|
143
|
+
no maintainer role or human pool membership. A `cta_` agent token gets 401
|
|
144
|
+
and cannot sign in to this page. Use the agent's `/agent/<pool>` endpoint
|
|
145
|
+
for machine access instead.
|
|
146
|
+
|
|
147
|
+
Personal OAuth can also start from the person's `/mcp/<pool>` connection with
|
|
148
|
+
`authorize_connector`, finishing its signed browser link. Trusted clients that manage personal credentials use only the actions listed
|
|
149
|
+
in the connector's `manage` field; the API contract below describes their
|
|
150
|
+
routes and preconditions. Shared credentials always require a maintainer.
|
|
37
151
|
|
|
38
152
|
## Operator data contract
|
|
39
153
|
|
|
40
154
|
`GET /ui/api/config`, owned by `operatorUi()`, returns `OperatorUiContract`
|
|
41
|
-
from
|
|
42
|
-
|
|
43
|
-
`
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
`
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`
|
|
67
|
-
|
|
68
|
-
and
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
155
|
+
(`OperatorUiContractV2`) from `@zackbart/connecta/ui`, `schemaVersion: 2`.
|
|
156
|
+
Its declarations ship in `dist/operator-ui/contract.d.ts` in the installed package. Schema
|
|
157
|
+
version 1, `hasGrant`, `you.grants`, and `you.permissions` were removed;
|
|
158
|
+
v2 keeps `you.interactive` to describe whether the session is interactive. It is the page's
|
|
159
|
+
only gate: a signed-out caller gets the auth provider's 401 challenge, and a
|
|
160
|
+
`cta_` agent token the machine-only 401 Bearer challenge every human route
|
|
161
|
+
gives it; a maintainer, or a person listed in a pool's `members`, gets 200
|
|
162
|
+
with `role` `"maintainer"` or `"member"`; anyone else gets the private JSON 404
|
|
163
|
+
`{ "error": "not found" }`. An open deployment's anonymous caller is
|
|
164
|
+
a maintainer. Every response is private, `no-store` JSON, and only GET is
|
|
165
|
+
allowed. One shape serves both roles; a field a role does not receive is
|
|
166
|
+
`null` or empty, never omitted.
|
|
167
|
+
|
|
168
|
+
The maintainer view carries:
|
|
169
|
+
|
|
170
|
+
- `config`, the construction-time `describeConfig()` snapshot, including
|
|
171
|
+
`maintainers` and each pool's `members`, and `configSources`, which labels
|
|
172
|
+
each serialized leaf as `default` or `config` from option presence rather
|
|
173
|
+
than equality with the default. Factory descriptions carry relative
|
|
174
|
+
`optionSources` paths so resolved module and transport defaults retain their
|
|
175
|
+
provenance. Paths use connector ids and pool names and are filtered after
|
|
176
|
+
disclosure; hidden values leave no provenance keys. Neither contains source
|
|
177
|
+
code or credential material.
|
|
178
|
+
- `root`: plain `/mcp`, its `readOnly`, and its `maintainers`, people only.
|
|
179
|
+
- `pools`: every declared pool with `humanPath` (`/mcp/<name>`), `agentPath`
|
|
180
|
+
(`/agent/<name>`), `readOnly`, `owner` (the Workspace address its agents act
|
|
181
|
+
as), its declared `tools` (never intersected; no `requireReadOnly` is ever
|
|
182
|
+
true), and its `members`, agents as `{ kind: "agent", name }`. Every listed
|
|
183
|
+
person carries a `label` from the same directory lookup activity actor
|
|
184
|
+
labels use, on an interactive read only, and `null` without a directory
|
|
185
|
+
(Cloudflare Access) or an entry. An open deployment's anonymous maintainer
|
|
186
|
+
reads every `owner` as `null`.
|
|
187
|
+
- `agents`: every agent declared in code, with its pools, its token slot
|
|
188
|
+
(`state`, `issuedAt`, `revokedAt`, `revision`) exactly as
|
|
189
|
+
`GET /ui/access-tokens` lists it, and `lastSeenAt`, the newest visible
|
|
190
|
+
activity row recorded for that agent, or `null` when activity is off or
|
|
191
|
+
none is visible. A slot read that fails answers 503 rather than drop agents.
|
|
192
|
+
- `matrix`: a cell per connector for plain `/mcp` (`pool: null`) and for each
|
|
193
|
+
pool that serves it, with that endpoint's tool names or `"all"` and
|
|
194
|
+
`runsAs`. A Workspace connector with a subject mapping is
|
|
195
|
+
`{ kind: "workspace", humans: "self", agents }`, `agents` being the pool's
|
|
196
|
+
owner, or `null` on plain `/mcp` and in an ownerless pool; a fixed subject is
|
|
197
|
+
`{ kind: "workspaceFixed", subject }`. A personal connector counts the
|
|
198
|
+
endpoint's people (the maintainers on plain `/mcp`) and how many have
|
|
199
|
+
connected in their own partition: a stored credential of the declared shape,
|
|
200
|
+
or an `ok` status. A shared connector names its `source`: `vault` (a saved
|
|
201
|
+
slot, with `savedAt`), `missing` (a slot with nothing saved, or shared OAuth
|
|
202
|
+
reporting it needs authorizing), `oauth` (a shared grant; grants carry no
|
|
203
|
+
saved time, so `savedAt` is `null`), `unauthenticated` (a remote MCP server
|
|
204
|
+
that declares no auth), or `config` (everything else, held by deployment
|
|
205
|
+
code).
|
|
206
|
+
- `live.connectors`: status and problem codes, complete registry tools with
|
|
207
|
+
their final read/write classification, catalog age in milliseconds, and
|
|
208
|
+
last-call time/outcome. Catalog descriptions and schemas are allowed;
|
|
209
|
+
grammar-failing names and addresses become `<withheld>`.
|
|
210
|
+
`auth.registrationPath` reports the selected downstream OAuth client
|
|
211
|
+
mechanism when known. Static and unobserved catalogs have a null age;
|
|
212
|
+
persisted catalogs retain their original fetch time.
|
|
213
|
+
- `live.activity`: available, unconfigured, forbidden, or unavailable history.
|
|
214
|
+
Last-call and last-seen lookups need the activity permission and read gate,
|
|
215
|
+
scan up to 1,000 recent rows, filter connector/tool grants, restrict personal
|
|
216
|
+
connectors to the caller's activity identity, and copy a validated timestamp
|
|
217
|
+
and outcome only. A null means unknown or absent in that window.
|
|
218
|
+
- `connectors: []`.
|
|
219
|
+
|
|
220
|
+
The member view is exactly that member's projection: `config`,
|
|
221
|
+
`configSources` and `root` are `null`, `live.connectors`, `agents` and
|
|
222
|
+
`matrix` are empty, and `live.activity` is `"forbidden"`. `pools` lists only
|
|
223
|
+
their pools, each with `owner: null` and `members: []`. `connectors` lists
|
|
224
|
+
each connector in those pools with its title, the member's pools that serve
|
|
225
|
+
it, its auth scope, the tools those pools grant with their classification,
|
|
226
|
+
`connection` (their own partition's state and problem code for a personal
|
|
227
|
+
connector, `null` for a shared one) and `manage`. `manage` is derived on the
|
|
228
|
+
server. A shared connector is always `{ kind: "none" }`. For a personal one,
|
|
229
|
+
the member's own permission (an interactive person in a pool that holds it)
|
|
230
|
+
gates every action. A credential slot offers `save` when a vault is
|
|
231
|
+
configured, `clear` when a value is stored in the member's partition, and
|
|
232
|
+
`test` when one is stored in the declared shape and the connector has the
|
|
233
|
+
matching test hook; an unreadable partition offers `save` alone, so the page
|
|
234
|
+
reads stored-ness from `actions`. OAuth offers `connect` and `restart` when
|
|
235
|
+
the connector has `startAuth`, `finishAuth` and `verifyState` and the
|
|
236
|
+
deployment can sign the connect hand-off, and `disconnect` when it has
|
|
237
|
+
`disconnectAuth`. No actions is `{ kind: "none" }`. The view carries no shared
|
|
238
|
+
credential status, catalog ages, last calls, other members, agents, owners or
|
|
239
|
+
activity. Status prose, error text, credential values or suffixes, arguments,
|
|
240
|
+
results, and code are excluded from both views. Probes run with bounded
|
|
241
|
+
concurrency and the configured probe deadline, and release their scopes. Every
|
|
242
|
+
vault, token-slot and activity read the view makes runs under that same
|
|
243
|
+
deadline and the request's signal, so a stalled store never hangs the page: it
|
|
244
|
+
degrades fail-closed, to `save` alone for a member's credential, `missing` or
|
|
245
|
+
an unconnected person in a matrix cell, unavailable activity, and a 503 for
|
|
246
|
+
the token slots.
|
|
247
|
+
|
|
248
|
+
`/ui/data`, `/ui/connectors/:id`, activity reads and access-token routes
|
|
249
|
+
require a maintainer and give anyone else the same private 404. The connector
|
|
250
|
+
auth routes, `/ui/oauth/<id>` and `/ui/credentials/<id>`, also admit a pool
|
|
251
|
+
member for a personal connector in one of their pools, in their own
|
|
252
|
+
partition. `/ui/oauth/<id>` gates each verb on its own hooks: a connect needs
|
|
253
|
+
`startAuth`, `finishAuth` and `verifyState`, a disconnect only
|
|
254
|
+
`disconnectAuth`. `/ui/credentials/<id>` refuses to clear an empty partition,
|
|
255
|
+
the caller's own for a personal connector or the shared slot, with 409
|
|
256
|
+
`{ "error": "no credential is stored to clear", "problem": "credential_required" }`,
|
|
257
|
+
as its test route refuses to test one; a value that cannot be read can still be
|
|
258
|
+
cleared. The routes thus accept what `manage` lists, with one recovery
|
|
259
|
+
exception: clearing a stored value that cannot be read is accepted although
|
|
260
|
+
`manage` lists only `save` in that state. Public HTML shells and static assets carry no catalog data.
|
|
261
|
+
Access-token management also requires an interactive session.
|
|
262
|
+
|
|
263
|
+
`GET /ui/api/config?connector=<id>` narrows the same contract to one connector
|
|
264
|
+
before status and catalog probes. For a maintainer, config, provenance, live
|
|
265
|
+
rows and matrix cells contain only that connector's facts; for a member,
|
|
266
|
+
`connectors` does. Pools keep their declared tools. An id outside the
|
|
267
|
+
caller's view receives a no-store 404. The selector never widens access.
|
|
80
268
|
|
|
81
269
|
`connecta doctor --config` fetches this authenticated contract and prints only
|
|
82
|
-
`config` as indented JSON
|
|
83
|
-
|
|
84
|
-
|
|
270
|
+
a maintainer's `config` as indented JSON; a member's view has none, and doctor
|
|
271
|
+
says the snapshot is for maintainers. It requires the UI module and the
|
|
272
|
+
existing doctor authentication environment variables; it runs no diagnostic
|
|
273
|
+
program, follows no redirects, and prints no raw HTTP failure body.
|
|
85
274
|
|
|
86
275
|
The operator shell uses React, TanStack Router/Query/Table, Radix, cmdk and
|
|
87
|
-
Tailwind v4.
|
|
276
|
+
Tailwind v4. Geist Sans, Geist Mono, CSS, JavaScript and dependency notices are hashed assets
|
|
88
277
|
under `/ui/assets/*`, served identically with immutable cache headers on Node
|
|
89
278
|
and Workers. HTML contains only mount points and escaped inert configuration;
|
|
90
|
-
it remains uncached.
|
|
279
|
+
it remains uncached. Ahead of the stylesheet, every operator page (sign-in
|
|
280
|
+
gate, member page, maintainer pages) loads a blocking hashed scheme initializer
|
|
281
|
+
of under 200 bytes, `src/operator-ui/app/scheme-init.ts`, with a plain
|
|
282
|
+
`<script src>` and no inline code. When the server set no `html[data-scheme]`
|
|
283
|
+
from a pinned `branding.theme.colorScheme`, it copies a saved `light` or `dark`
|
|
284
|
+
from local storage key `connecta:scheme` onto that attribute, ignoring storage
|
|
285
|
+
errors, so the first frame already has the viewer's scheme. The deferred bundle
|
|
286
|
+
learns of a pin from `schemePinned` in the inert configuration; Appearance
|
|
287
|
+
writes the key and moves the attribute live, and is read-only under a pin. Every
|
|
288
|
+
local and session storage access in the UI tolerates storage that throws, as in
|
|
289
|
+
private browsing: a read finds nothing stored and a write keeps nothing, so a
|
|
290
|
+
bearer token is not remembered there. `generated.ts` is ignored and generated before build and
|
|
91
291
|
test; `check:operator-ui` detects stale assets and shared page styles. The UI
|
|
92
292
|
stays behind `./ui`, outside the root import graph. The identity-fenced store
|
|
93
|
-
owns authenticated reads and existing mutations.
|
|
94
|
-
|
|
293
|
+
owns authenticated reads and existing mutations. An Access-only shell selects
|
|
294
|
+
Access even when the HTML request has no trusted context; only authenticated
|
|
295
|
+
API responses establish the session. A gated Access session offers Retry.
|
|
296
|
+
Focus, visibility, and timer-driven recovery share one admission-read schedule
|
|
297
|
+
with at least two seconds between passive attempts. An admission read takes
|
|
298
|
+
the contract first and, for a maintainer, then `/ui/data` and the connector
|
|
299
|
+
details, which reuse that contract rather than read it again. An in-flight
|
|
300
|
+
passive attempt coalesces returns until its admission read finishes, so slow
|
|
301
|
+
successful reads can publish. Each admission read shares one 15-second
|
|
302
|
+
deadline, including token acquisition, fetches and response bodies. This is an admission deadline, not a request
|
|
303
|
+
lifetime limit: it releases the recovery guard and exposes Retry without aborting
|
|
304
|
+
the pending read or invalidating its identity/revision fence. A late healthy
|
|
305
|
+
response still publishes if that cycle is current. Passive timers and returns
|
|
306
|
+
coalesce onto the pending cycle, including after its deadline; they never start
|
|
307
|
+
duplicate summary, token, config, detail or body reads. The passive retry schedule
|
|
308
|
+
stays bounded and does not reset its budget on a deadline. Retry remains available
|
|
309
|
+
during recovery configuration loading and supersedes and aborts the old cycle;
|
|
310
|
+
identity changes, navigation and connector-page unmount also cancel it. Navigation
|
|
311
|
+
that cancels pending data schedules a bounded reread for the destination. Failed reads retry after
|
|
312
|
+
2, 2, 4, and 8 seconds. Refusals preserve the throttle and retry budget. After
|
|
313
|
+
those four automatic retries, a focus return can request one more read after
|
|
314
|
+
the eight-second backoff, without replenishing the automatic budget. Retry
|
|
315
|
+
resets the budget with a 150 ms click debounce. Successful reads and explicit
|
|
316
|
+
identity transitions also reset recovery. Identity changes
|
|
317
|
+
cancel pending retries and fence out responses from the previous identity.
|
|
318
|
+
Queued focus callbacks carry the same identity fence. Explicit sign-out
|
|
319
|
+
suppresses passive reads until an intentional sign-in or a new Clerk session.
|
|
320
|
+
|
|
321
|
+
Catalog and connector auth details share one revisioned refresh cycle. Each
|
|
322
|
+
completed connector publishes its catalog facts and auth controls together,
|
|
323
|
+
while a slow provider leaves other rows usable.
|
|
324
|
+
Catalog refresh, connector refresh, and mutation follow-up reads update both
|
|
325
|
+
consumers together. A later refresh or mutation invalidates an older cycle's publication fence
|
|
326
|
+
without aborting its read, and a failed contract read clears its old snapshot;
|
|
327
|
+
the next refresh then reads the contract before any connector detail. After an explicit OAuth
|
|
328
|
+
start, visible tabs poll only that connector's read-only catalog and auth facts
|
|
329
|
+
every two seconds for up to 30 seconds. The scoped result replaces only that
|
|
330
|
+
connector's matching live row and auth controls. Success, a failed read or status,
|
|
331
|
+
disconnect, navigation away from the connector, unmount, or identity reset ends
|
|
332
|
+
polling and aborts its in-flight reads. The deadline also aborts a stalled read.
|
|
333
|
+
A later focus return can request another status read. Recovery never starts OAuth
|
|
334
|
+
or replays a mutation.
|
|
335
|
+
Unreadable credential metadata uses `configured: null`, including named fields,
|
|
336
|
+
and renders as unavailable with a retry prompt. It does not claim that the slot
|
|
337
|
+
is empty. Endpoints, Connectors, connector
|
|
338
|
+
detail, Settings, and the member page consume the typed contract; Activity opens
|
|
339
|
+
only to a maintainer whose contract reports readable history. Connector detail
|
|
340
|
+
reads auth permissions from its `/ui/data` connector. Activity retains
|
|
95
341
|
its authenticated data routes. Connector detail tabs live
|
|
96
342
|
in the URL hash; Activity filters live in the query string and apply to loaded
|
|
97
|
-
history. Both `/ui/activity` and `/ui/api/activity` require
|
|
98
|
-
pass the optional activity `readGate`.
|
|
99
|
-
|
|
343
|
+
history. Both `/ui/activity` and `/ui/api/activity` require a maintainer
|
|
344
|
+
principal, interactive or not, and pass the optional activity `readGate`.
|
|
345
|
+
Interactive and machine maintainer reads share the same history disclosure rules.
|
|
100
346
|
Connector/tool grants and grants for the recorded pool filter each event. Shared
|
|
101
347
|
connector history can include other principals' events, with recorded request
|
|
102
348
|
IDs, validated client name/version and package version, and actor kind, ID and
|
|
@@ -118,12 +364,31 @@ id and typed actor when available, otherwise a fresh id and system actor. No
|
|
|
118
364
|
names, descriptions or schemas enter the event. Private catalog changes require
|
|
119
365
|
a matching principal owner even when the connector uses shared auth. Empty credential declarations
|
|
120
366
|
report `credential_required` before running a connector status or catalog probe.
|
|
121
|
-
The
|
|
122
|
-
and
|
|
367
|
+
The top bar shows deployment branding and a name breadcrumb, then Search (the
|
|
368
|
+
command palette), Appearance, and the session action (Change token or Sign out)
|
|
369
|
+
at one quiet size; a member's top bar has only branding, the account and the
|
|
370
|
+
session action. The tab row lists Endpoints, Connectors, Activity,
|
|
371
|
+
Tokens, and Settings. Activity and Tokens keep their permission gates; a gated
|
|
372
|
+
viewer sees no operator navigation. The command palette searches visible pages,
|
|
373
|
+
connectors and tools, opening connector results on Tools. `/access` redirects
|
|
374
|
+
to `/`, `/tools` to `/connectors`, and `/config` to `/settings` in the browser
|
|
375
|
+
with history replacement. Connector hashes `#config`, `#auth` and `#diagnostics`
|
|
376
|
+
redirect to `#connection`, preserving query parameters such as signed handoffs.
|
|
377
|
+
Token controls retain their existing permission gate.
|
|
123
378
|
Configuration remains in deployment code. The UI mutates only credentials,
|
|
124
|
-
OAuth connections and
|
|
379
|
+
OAuth connections and agent tokens through the existing routes.
|
|
380
|
+
|
|
381
|
+
## Contributor reference
|
|
382
|
+
|
|
383
|
+
### Source and tests
|
|
125
384
|
|
|
126
|
-
|
|
385
|
+
The browser store reads only v2 and checks `role` before reading a
|
|
386
|
+
maintainer-only field. `test/fixtures/operator-contract-v2.ts` holds
|
|
387
|
+
maintainer and member fixtures, and `test/helpers/operator-member-view.ts`
|
|
388
|
+
checks a member response's exact shape and compares its values with a
|
|
389
|
+
projection built from config, membership, the member's own partition status,
|
|
390
|
+
and each personal connector's exact `manage`;
|
|
391
|
+
`test/operator-contract-server.test.ts` runs it against real responses.
|
|
127
392
|
|
|
128
393
|
The contract type is [contract.ts](https://github.com/zackbart/connecta/blob/main/src/operator-ui/contract.ts).
|
|
129
394
|
[UI routes](https://github.com/zackbart/connecta/blob/main/src/routes/ui.ts) and
|
|
@@ -2,17 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Use this upgrade guide when moving a Stripe, Notion, Vercel, or Cloudflare
|
|
4
4
|
deployment from 0.30 to 0.31, where `auth` selects each provider's
|
|
5
|
-
implementation
|
|
6
|
-
The [0.31.0 release notes](https://github.com/zackbart/connecta/blob/main/release-notes/0.31.0.md) summarize the change.
|
|
5
|
+
implementation.
|
|
7
6
|
[Deployment upgrades](./deploying.md#upgrade-an-existing-deployment) cover other
|
|
8
7
|
version changes; [integrating services](./integrating.md) covers new connectors.
|
|
9
8
|
|
|
10
9
|
A dual provider requires `auth`. `{ type: "oauth" }` connects the vendor's
|
|
11
10
|
hosted MCP server, OAuth only. A key type connects Connecta's REST connector
|
|
12
11
|
with an operator-managed credential. There is no default, and one connector id
|
|
13
|
-
uses one implementation: configure two ids for both.
|
|
14
|
-
[decision record](https://github.com/zackbart/connecta/blob/main/decisions/0005-auth-selects-implementation.md)
|
|
15
|
-
explains why.
|
|
12
|
+
uses one implementation: configure two ids for both.
|
|
16
13
|
|
|
17
14
|
## Stripe
|
|
18
15
|
|
|
@@ -62,6 +59,10 @@ contracts: search finds operations in a pinned API index, every call is
|
|
|
62
59
|
checked against that index before it is sent, results arrive as
|
|
63
60
|
`{ status, data, page? }`, and POST writes send the caller's `idempotencyKey`
|
|
64
61
|
or a generated one as `Idempotency-Key` and return it (DELETE sends none).
|
|
62
|
+
Caller-supplied keys may contain up to 255 characters. An ambiguous POST write
|
|
63
|
+
also returns the key in `uncertainCall.recovery.idempotencyKey`, including when
|
|
64
|
+
the call deadline interrupts it. See [argument recovery](./meta-tools.md#argument-recovery)
|
|
65
|
+
before retrying.
|
|
65
66
|
Every request, v1 and v2, sends `Stripe-Version: 2026-09-30.endive`, the
|
|
66
67
|
version of the pinned index, whatever the account's default API version, so
|
|
67
68
|
response shapes and accepted parameters follow that version. Check fields
|
|
@@ -73,9 +74,7 @@ A key whose `sk_live_`/`rk_live_` or `sk_test_`/`rk_test_` prefix contradicts
|
|
|
73
74
|
Lost on the key path: natural-language Sigma (`stripe_analytics`), metrics,
|
|
74
75
|
documentation search, the implementation planner, reports, and feedback exist
|
|
75
76
|
only on the hosted OAuth connection. Programs calling those tools on a key
|
|
76
|
-
connector need an OAuth connector beside it.
|
|
77
|
-
[Stripe skill](https://github.com/zackbart/connecta/blob/main/src/providers/stripe/SKILL.md)
|
|
78
|
-
owns the conventions for both.
|
|
77
|
+
connector need an OAuth connector beside it. Read the connector runtime guide with `connecta.skill("connector:<id>")` in `execute_code` for its usage conventions.
|
|
79
78
|
|
|
80
79
|
## Notion
|
|
81
80
|
|
|
@@ -101,6 +100,15 @@ connectors: [
|
|
|
101
100
|
| `integration_list_comments`, `integration_add_comment` | `notion_api_read` `GET /v1/comments`; `notion_api_write` `POST /v1/comments`. |
|
|
102
101
|
| `integration_update_page_properties`, `integration_trash_page` | `notion_api_write` `PATCH /v1/pages/{page_id}` with `properties`, or `in_trash` to trash or restore. |
|
|
103
102
|
|
|
103
|
+
Both auth variants accept optional `callAdmission`. On a token connector it
|
|
104
|
+
replaces the whole default policy of 180 calls per minute and 3 concurrent
|
|
105
|
+
per runtime. Malformed policies throw at construction. Notion's
|
|
106
|
+
[request limits](https://developers.notion.com/reference/request-limits) allow
|
|
107
|
+
600 requests per minute per connection on Business and Enterprise and 180 on
|
|
108
|
+
other plans, with a separate workspace-wide limit shared by all connections.
|
|
109
|
+
Account for other runtimes and tools that make multiple HTTP requests when
|
|
110
|
+
choosing an override.
|
|
111
|
+
|
|
104
112
|
The token connector gains Connecta's generic REST tools over Notion's pinned
|
|
105
113
|
API index (`notion_api_search`, `notion_api_details`, `notion_api_read`,
|
|
106
114
|
`notion_api_write`), so every public operation is reachable with the bot's
|
|
@@ -119,8 +127,7 @@ duplication, team and skill search, attachment downloads, or page-to-skill
|
|
|
119
127
|
conversion. An OAuth connector acts as the user, and has none of the generic
|
|
120
128
|
REST tools or the `integration_*` projections and authoring helpers. Configure
|
|
121
129
|
both ids when a deployment needs both; a failed call is never retried on the
|
|
122
|
-
other.
|
|
123
|
-
owns the conventions for both.
|
|
130
|
+
other. Read the connector runtime guide with `connecta.skill("connector:<id>")` in `execute_code` for its usage conventions.
|
|
124
131
|
|
|
125
132
|
## Vercel
|
|
126
133
|
|
|
@@ -156,7 +163,7 @@ variable tools (`list_project_env_vars`, `upsert_project_env_var`,
|
|
|
156
163
|
(the runtime stream, stopped after `waitMs` or `maxRows`), and
|
|
157
164
|
`vercel_api_upload`.
|
|
158
165
|
|
|
159
|
-
Value safety follows a reviewed table
|
|
166
|
+
Value safety follows a reviewed table bundled with the connector.
|
|
160
167
|
Every operation whose response schema in the pinned spec may carry a credential
|
|
161
168
|
or a stored secret has a verdict: refused (credential minting, Connect
|
|
162
169
|
authorization, decrypted environment values, Global Config items and tokens,
|
|
@@ -186,9 +193,7 @@ The hosted connection now lists `filter_project_envs`, `get_project_env`,
|
|
|
186
193
|
return decrypted values, so they are reviewed as writes, and a `readOnly`
|
|
187
194
|
endpoint refuses them. Vercel admits only reviewed and approved MCP clients to its
|
|
188
195
|
hosted server; if authorization is refused for that reason, the deployment
|
|
189
|
-
needs Vercel's approval or a token connector.
|
|
190
|
-
[Vercel skill](https://github.com/zackbart/connecta/blob/main/src/providers/vercel/SKILL.md)
|
|
191
|
-
owns the conventions for both.
|
|
196
|
+
needs Vercel's approval or a token connector. Read the connector runtime guide with `connecta.skill("connector:<id>")` in `execute_code` for its usage conventions.
|
|
192
197
|
|
|
193
198
|
## Cloudflare
|
|
194
199
|
|
|
@@ -254,9 +259,7 @@ Lost on each path. OAuth has no index validation, named tools, GraphQL tool,
|
|
|
254
259
|
upload tool, or pin; Cloudflare's OAuth grant is the only boundary. A key has
|
|
255
260
|
no hosted `search` over Cloudflare's live OpenAPI document; the pinned index
|
|
256
261
|
replaces it and `providers:check` reports when it falls behind. A Global API
|
|
257
|
-
Key cannot reach R2, which accepts API tokens only.
|
|
258
|
-
[Cloudflare skill](https://github.com/zackbart/connecta/blob/main/src/providers/cloudflare/SKILL.md)
|
|
259
|
-
owns the conventions for both.
|
|
262
|
+
Key cannot reach R2, which accepts API tokens only. Read the connector runtime guide with `connecta.skill("connector:<id>")` in `execute_code` for its usage conventions.
|
|
260
263
|
|
|
261
264
|
## Value safety on every key connector
|
|
262
265
|
|
|
@@ -289,12 +292,16 @@ one; read or rotate withheld secrets in the vendor's dashboard.
|
|
|
289
292
|
Failures of credential-bearing operations keep Stripe's type, code, and
|
|
290
293
|
param but not its message. Create client-side sessions and links from your
|
|
291
294
|
own server code.
|
|
292
|
-
- **Notion** results withhold the
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
- **Notion** REST results and error text withhold the whole query and
|
|
296
|
+
fragment of canonical Notion file links, including links embedded in
|
|
297
|
+
Markdown and async task results. External proxy URLs keep their bytes;
|
|
298
|
+
AWS and Google signing-parameter values are withheld at any host. Writes
|
|
299
|
+
carrying the plain or encoded `[redacted]` placeholder in a Notion file
|
|
300
|
+
link's own query or fragment are refused before dispatch. See the
|
|
301
|
+
connector runtime guide through `connecta.skill("connector:<id>")` in `execute_code` for recognized hosts and scanning limits. Credential-named fields,
|
|
302
|
+
including database properties named like credentials, read as
|
|
303
|
+
`"[redacted]"`. Failures of the OAuth, file upload, bot user, and agent
|
|
304
|
+
operations keep Notion's code but not its message.
|
|
298
305
|
- **Vercel** replaces environment values with `"[redacted]"` instead of
|
|
299
306
|
dropping the field, and withholds Vercel's error text for every reviewed
|
|
300
307
|
operation and every operation whose request takes a credential-named
|
|
@@ -306,3 +313,10 @@ one; read or rotate withheld secrets in the vendor's dashboard.
|
|
|
306
313
|
destinations to their scheme and host. A credential-named field now loses
|
|
307
314
|
its whole value, not only its strings (a `cookies` list, a variable named
|
|
308
315
|
`API_KEY`).
|
|
316
|
+
|
|
317
|
+
## Contributor reference
|
|
318
|
+
|
|
319
|
+
[Decision 0005](https://github.com/zackbart/connecta/blob/main/decisions/0005-auth-selects-implementation.md)
|
|
320
|
+
explains why auth selects the implementation. Maintained provider source
|
|
321
|
+
skills and review tables live under `src/providers/` in the repository;
|
|
322
|
+
`src/providers/vercel/value-safety.ts` owns Vercel's reviewed table.
|
|
@@ -7,8 +7,8 @@ version changes; [integrating services](./integrating.md) covers new connectors.
|
|
|
7
7
|
|
|
8
8
|
This is the Phase 1 item 5d migration input for [Phase 5 release #709](https://github.com/zackbart/connecta/issues/709).
|
|
9
9
|
Deploy it with the consolidated 0.29 release, not while the rework is in progress.
|
|
10
|
-
|
|
11
|
-
connector ids
|
|
10
|
+
Deployments that use Notion or Cloudflare must check their actual grants and
|
|
11
|
+
connector ids in deployment configuration before that release.
|
|
12
12
|
The provider audit establishes available auth modes, not production OAuth grants.
|
|
13
13
|
|
|
14
14
|
Cloudflare's part of this guide is superseded: `cloudflare()` now selects its
|