@zackbart/connecta 0.31.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 +97 -0
- package/README.md +30 -20
- package/bin/connecta.mjs +25 -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/auth-elicitation.js +1 -1
- package/dist/call-admission-context.js +15 -0
- package/dist/call-admission.js +30 -43
- package/dist/call-recovery.js +6 -2
- package/dist/catalog-service.js +7 -2
- package/dist/config-value-sources.js +14 -9
- package/dist/config.d.ts +58 -78
- package/dist/config.js +143 -47
- package/dist/connector-access.d.ts +4 -33
- 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/guarded-fetch.d.ts +9 -0
- package/dist/connectors/guarded-fetch.js +7 -0
- package/dist/connectors/remote-mcp.js +2 -0
- package/dist/describe-config.d.ts +32 -7
- package/dist/describe-config.js +9 -18
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -0
- package/dist/execute.js +16 -14
- package/dist/index.d.ts +4 -3
- package/dist/index.js +30 -10
- package/dist/invocation.js +12 -7
- package/dist/membership.d.ts +51 -0
- package/dist/membership.js +121 -0
- package/dist/meta-tools.js +17 -19
- package/dist/module-contracts.d.ts +23 -6
- package/dist/operator-record.d.ts +2 -2
- package/dist/operator-record.js +2 -2
- package/dist/operator-ui/agents.d.ts +74 -0
- package/dist/operator-ui/agents.js +104 -0
- package/dist/operator-ui/contract.d.ts +151 -29
- 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 +15 -7
- package/dist/operator-ui/view.d.ts +84 -19
- package/dist/operator-ui/view.js +83 -21
- package/dist/page-styles.js +1 -1
- package/dist/program-writes.js +2 -2
- package/dist/provider.d.ts +63 -11
- package/dist/provider.js +46 -7
- package/dist/providers/_shared/google/workspace.d.ts +53 -16
- package/dist/providers/_shared/google/workspace.js +31 -9
- 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/breeze/skill.generated.js +2 -2
- 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 +2 -2
- package/dist/providers/cloudflare/value-safety.js +32 -0
- package/dist/providers/docs/index.d.ts +1 -1
- package/dist/providers/docs/index.js +5 -5
- package/dist/providers/docs/skill.generated.js +2 -2
- package/dist/providers/drive/index.d.ts +1 -1
- package/dist/providers/drive/index.js +4 -4
- package/dist/providers/drive/skill.generated.js +2 -2
- package/dist/providers/forms/index.d.ts +1 -1
- package/dist/providers/forms/index.js +5 -5
- package/dist/providers/forms/skill.generated.js +2 -2
- package/dist/providers/github/skill.generated.js +2 -2
- package/dist/providers/gmail/index.d.ts +1 -1
- package/dist/providers/gmail/index.js +279 -26
- package/dist/providers/gmail/skill.generated.js +2 -2
- package/dist/providers/linear/index.js +1 -1
- package/dist/providers/mixpanel/index.d.ts +27 -12
- package/dist/providers/mixpanel/index.js +58 -6
- package/dist/providers/mixpanel/operations.js +20 -0
- package/dist/providers/mixpanel/rest.js +603 -0
- package/dist/providers/mixpanel/skill.generated.js +3 -2
- package/dist/providers/mixpanel/value-safety.js +16 -0
- package/dist/providers/notion/index.d.ts +7 -0
- package/dist/providers/notion/index.js +116 -11
- package/dist/providers/notion/rest.js +183 -24
- package/dist/providers/notion/skill.generated.js +4 -4
- package/dist/providers/notion/value-safety.js +30 -5
- package/dist/providers/overflow/index.js +1 -1
- package/dist/providers/planning-center/index.d.ts +27 -0
- package/dist/providers/planning-center/index.js +287 -25
- package/dist/providers/planning-center/skill.generated.js +24 -4
- package/dist/providers/sheets/index.d.ts +4 -1
- package/dist/providers/sheets/index.js +9 -6
- package/dist/providers/sheets/skill.generated.js +2 -2
- package/dist/providers/slides/index.d.ts +1 -1
- package/dist/providers/slides/index.js +6 -6
- package/dist/providers/slides/skill.generated.js +2 -2
- package/dist/providers/stripe/rest.js +9 -2
- package/dist/providers/stripe/skill.generated.js +2 -2
- package/dist/providers/stripe/value-safety.js +22 -0
- package/dist/providers/vercel/index.js +2 -2
- package/dist/providers/vercel/rest.js +20 -2
- package/dist/providers/vercel/skill.generated.js +2 -2
- package/dist/providers/vercel/value-safety.js +22 -0
- package/dist/providers/wispr-flow/index.d.ts +14 -0
- package/dist/providers/wispr-flow/index.js +117 -0
- package/dist/providers/wispr-flow/skill.generated.js +8 -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 +155 -85
- package/dist/routes/oauth-management.js +11 -5
- package/dist/routes/oauth.js +3 -9
- package/dist/routes/operator.js +25 -17
- 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 +8 -0
- package/dist/skills.js +5 -4
- package/dist/storage/keys.js +9 -1
- package/dist/tool-safety.js +13 -5
- package/dist/types.d.ts +12 -1
- package/dist/ui.d.ts +2 -2
- package/dist/ui.js +17 -15
- package/dist/usage-guide.js +3 -3
- 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 +378 -58
- package/documentation/auth.md +806 -215
- package/documentation/code-mode.md +93 -81
- package/documentation/deploying.md +128 -26
- package/documentation/integrating.md +145 -22
- package/documentation/meta-tools.md +58 -46
- package/documentation/migration-0.33.md +344 -0
- package/documentation/operating.md +14 -9
- package/documentation/operator-tests.md +117 -31
- package/documentation/operator-ui.md +326 -55
- package/documentation/provider-auth-migration.md +42 -27
- package/documentation/provider-migration-0.29.md +3 -3
- package/examples/worker/AGENTS.md +35 -8
- package/examples/worker/README.md +92 -53
- package/examples/worker/src/connecta.config.ts +41 -20
- package/examples/worker/wrangler.jsonc +3 -0
- package/package.json +7 -2
- package/templates/node/.env.example +3 -0
- package/templates/node/AGENTS.md +33 -10
- package/templates/node/Dockerfile +2 -2
- package/templates/node/README.md +71 -44
- 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 +33 -12
- package/templates/node/src/rotate-token.ts +17 -0
- package/dist/tool-safety.d.ts +0 -9
- package/templates/node/src/provision-token.ts +0 -17
package/templates/node/README.md
CHANGED
|
@@ -8,11 +8,12 @@ maintenance. This README and [local agent instructions](./AGENTS.md) own the
|
|
|
8
8
|
runnable steps for a copied Node deployment.
|
|
9
9
|
|
|
10
10
|
This is the prescribed Node deployment. It runs locally from source and as
|
|
11
|
-
a container. Install,
|
|
11
|
+
a container. Install, issue the declared `local-machine` agent's token, then
|
|
12
|
+
start it:
|
|
12
13
|
|
|
13
14
|
```sh
|
|
14
15
|
npm install
|
|
15
|
-
npm run --silent
|
|
16
|
+
npm run --silent rotate-token -- local-machine
|
|
16
17
|
# Save the returned cta_ token privately. It is shown only once.
|
|
17
18
|
npm start
|
|
18
19
|
```
|
|
@@ -24,39 +25,57 @@ warning, and npm 12 does not block the script. A later esbuild version needs a
|
|
|
24
25
|
new explicit review and approval; do not replace the pinned entry with a broad
|
|
25
26
|
package-name approval.
|
|
26
27
|
|
|
27
|
-
Point an MCP client at `http://localhost:8787/
|
|
28
|
-
|
|
28
|
+
Point an agent's MCP client at `http://localhost:8787/agent/local-machine`, the agent
|
|
29
|
+
endpoint of the pool that lists `agent:local-machine`, with
|
|
30
|
+
`Authorization: Bearer <returned-cta-token>`. Agents use only `/agent/<pool>`:
|
|
31
|
+
`/mcp` and `/mcp/<pool>` are for people and refuse `cta_` tokens, and plain
|
|
32
|
+
`/mcp` serves only the `maintainers`. `CONNECTA_TOKEN` is a client and
|
|
29
33
|
doctor variable only. Setting it never configures server authentication.
|
|
30
34
|
|
|
31
|
-
`accessTokens(storage)` is always installed. With no
|
|
32
|
-
Clerk keys, the server can start and answer `/health`, but every MCP
|
|
33
|
-
is refused. There is no open startup or configured static bearer
|
|
35
|
+
`accessTokens(storage)` is always installed. With no issued agent token and
|
|
36
|
+
no Clerk keys, the server can start and answer `/health`, but every MCP
|
|
37
|
+
request is refused. There is no open startup or configured static bearer
|
|
38
|
+
fallback.
|
|
34
39
|
|
|
35
|
-
##
|
|
40
|
+
## Agent tokens
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
on
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
Machine clients are agents, declared by name in `agents` in
|
|
43
|
+
`src/connecta.config.ts`; the template declares `local-machine`. Each agent
|
|
44
|
+
has one token. Run `npm run --silent rotate-token -- <agent>` from this
|
|
45
|
+
project on a trusted machine to issue it, or to rotate it: the previous secret
|
|
46
|
+
stops working on its next request. `src/rotate-token.ts` loads the same
|
|
47
|
+
configuration the server does, so it uses the same database and refuses an
|
|
48
|
+
agent the configuration does not declare. If you override the database path,
|
|
49
|
+
use the same `CONNECTA_DATABASE` for rotation and startup:
|
|
43
50
|
|
|
44
51
|
```sh
|
|
45
52
|
export CONNECTA_DATABASE=/absolute/path/connecta.sqlite
|
|
46
|
-
npm run --silent
|
|
53
|
+
npm run --silent rotate-token -- local-machine
|
|
47
54
|
npm start
|
|
48
55
|
```
|
|
49
56
|
|
|
50
57
|
The local commands read the process environment; they do not load `.env`.
|
|
51
58
|
Compose reads `.env` for the container commands below. Keep the returned
|
|
52
|
-
secret in a client secret store and out of source control and logs.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
authority
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
storage
|
|
59
|
-
|
|
59
|
+
secret in a client secret store and out of source control and logs. A
|
|
60
|
+
rotation cannot recover an old secret; only the hash persists. An agent has no
|
|
61
|
+
human principal, no personal connectors, and no interactive management
|
|
62
|
+
authority; deployment identity and pool rules decide its access on every
|
|
63
|
+
request through `identity.agent`. To stop an agent, remove its name from
|
|
64
|
+
`agents` and restart, or revoke its token with
|
|
65
|
+
`new AccessTokenManager(storage, { agents }).revoke(name)` against the same
|
|
66
|
+
storage. An explicitly permitted Clerk operator can also issue, rotate, and
|
|
67
|
+
revoke from the operator UI. Never expose these scripts as an HTTP route or
|
|
68
|
+
run them at startup.
|
|
69
|
+
|
|
70
|
+
### Tokens issued before agents
|
|
71
|
+
|
|
72
|
+
Tokens from earlier releases stay in storage but stop admitting until they are
|
|
73
|
+
bound to an agent. Declare the agent, then run `npm run adopt-token` with no
|
|
74
|
+
arguments to list the machine tokens that can be bound, and
|
|
75
|
+
`npm run adopt-token -- <token-id> <agent>` to bind one, so that machine's
|
|
76
|
+
existing secret keeps working. A token binds once, and only to an agent whose
|
|
77
|
+
token was never issued. Human-bound tokens issued from the operator UI cannot
|
|
78
|
+
be adopted and stay refused; issue the agent a new token instead.
|
|
60
79
|
|
|
61
80
|
## Run it in Docker
|
|
62
81
|
|
|
@@ -66,12 +85,12 @@ Same source, same configuration, one long-lived service:
|
|
|
66
85
|
cp .env.example .env
|
|
67
86
|
# edit .env for the database path and any optional modules
|
|
68
87
|
docker compose build
|
|
69
|
-
docker compose run --rm --no-deps connecta npm run --silent
|
|
88
|
+
docker compose run --rm --no-deps connecta npm run --silent rotate-token -- local-machine
|
|
70
89
|
# Save the returned cta_ token privately for clients and doctor.
|
|
71
90
|
docker compose up -d
|
|
72
91
|
```
|
|
73
92
|
|
|
74
|
-
The
|
|
93
|
+
The rotation container writes through the installed package API into the
|
|
75
94
|
same named volume and `CONNECTA_DATABASE` as the service. An empty volume
|
|
76
95
|
admits no machine client. Compose never passes `CONNECTA_TOKEN` to the server;
|
|
77
96
|
no environment value can substitute for a stored token.
|
|
@@ -121,12 +140,14 @@ whether or not it is switched on.
|
|
|
121
140
|
|
|
122
141
|
The template explicitly enables `ui: operatorUi()` from
|
|
123
142
|
`@zackbart/connecta/ui`. Open `http://localhost:8787/` and supply a
|
|
124
|
-
|
|
143
|
+
declared agent's token to inspect Connections. Sign in with Clerk for human
|
|
125
144
|
connection management. Omit that option and import for an API-only
|
|
126
145
|
server. OAuth callbacks remain in core even with no UI.
|
|
127
146
|
|
|
128
|
-
The page labels each tool as a read or write
|
|
129
|
-
read-only
|
|
147
|
+
The page labels each tool as a read or write and each endpoint as writable or
|
|
148
|
+
read-only. `src/connecta.config.ts` must set `readOnly`: a read-only endpoint
|
|
149
|
+
refuses every write call and leaves write tools out of search, and the host
|
|
150
|
+
controls approval on a writable one. For
|
|
130
151
|
classified connection failures it offers a fixed repair prompt, and its
|
|
131
152
|
endpoint section has client setup commands for `/mcp` and any pool available
|
|
132
153
|
to the signed-in identity. Those commands contain no bearer token.
|
|
@@ -142,7 +163,10 @@ Connection management needs an interactive identity. A machine access token
|
|
|
142
163
|
never authorizes browser credential mutations. `@clerk/backend`
|
|
143
164
|
ships as a dependency of this template. To enable Clerk, set both
|
|
144
165
|
`CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` (one without the other refuses to
|
|
145
|
-
start) and
|
|
166
|
+
start), set `PUBLIC_URL`, and list your Clerk user id in `CONNECTA_MAINTAINERS`
|
|
167
|
+
(comma-separated; startup refuses Clerk without a maintainer). Maintainers
|
|
168
|
+
alone use plain `/mcp` and the operator UI; add other people to a pool's
|
|
169
|
+
`members` in `src/connecta.config.ts`.
|
|
146
170
|
Enable `aud_claim_enabled: true` in Clerk's instance OAuth application settings
|
|
147
171
|
(`PATCH /v1/instance/oauth_application_settings` in Clerk's Backend API), then
|
|
148
172
|
read the setting back. Both JWT and opaque OAuth tokens are supported.
|
|
@@ -162,18 +186,20 @@ audience. New DCR registrations need new entries, so prefer audience binding
|
|
|
162
186
|
for standard host onboarding. Clerk session tokens work only on operator
|
|
163
187
|
routes. [Inbound auth](https://github.com/zackbart/connecta/blob/main/documentation/auth.md#clerk-oauth-tokens-and-operator-sessions)
|
|
164
188
|
explains configuration, verification, and fixed rejection reason codes.
|
|
165
|
-
Machine clients
|
|
166
|
-
through `accessTokens(storage)`, which `src/connecta.config.ts`
|
|
167
|
-
the database.
|
|
168
|
-
|
|
189
|
+
Machine clients are the declared `agents`, each using a connecta-issued
|
|
190
|
+
`cta_` token through `accessTokens(storage)`, which `src/connecta.config.ts`
|
|
191
|
+
configures on the database. A signed-in maintainer issues, rotates, and
|
|
192
|
+
revokes them from the operator UI. Trusted local rotation above works without
|
|
169
193
|
Clerk and never requires opening the server.
|
|
170
194
|
|
|
171
|
-
Set
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
`
|
|
195
|
+
Set who uses what in code: `maintainers` for plain `/mcp` and the operator UI,
|
|
196
|
+
and each pool's `members` for `/mcp/<pool>` (people) and `/agent/<pool>`
|
|
197
|
+
(agents), which serve exactly that pool's `tools`. Agent endpoints publish no
|
|
198
|
+
protected-resource metadata and accept only `cta_` tokens. Maintainers alone
|
|
199
|
+
administer shared credentials and OAuth grants, manage agent tokens, and read
|
|
200
|
+
activity. Use `authScope: "personal"` for a connector where each person should
|
|
201
|
+
connect their own downstream account: a member connects their own account on
|
|
202
|
+
the personal connectors in their pools.
|
|
177
203
|
|
|
178
204
|
### Credential vault
|
|
179
205
|
|
|
@@ -218,7 +244,7 @@ Diagnostics are independent. Keep the default logger or provide your own;
|
|
|
218
244
|
|
|
219
245
|
The UI displays connections and current permissions. Configuration still owns
|
|
220
246
|
the connector set, tool definitions, and access rules. Access token management
|
|
221
|
-
requires
|
|
247
|
+
requires a signed-in Clerk maintainer. There is no team roster or policy editor.
|
|
222
248
|
|
|
223
249
|
## Deployment contract
|
|
224
250
|
|
|
@@ -266,8 +292,9 @@ feature should not leave a tab behind.
|
|
|
266
292
|
Upgrading from v0.23 does not require rotating managed `cta_…` tokens. Import
|
|
267
293
|
`accessTokens` from `@zackbart/connecta/auth/access-tokens`, replace the old
|
|
268
294
|
`accessTokens: true` with `accessTokens: accessTokens(storage)`, and keep the
|
|
269
|
-
same persistent storage namespace and
|
|
270
|
-
`identity.
|
|
271
|
-
|
|
272
|
-
|
|
295
|
+
same persistent storage namespace. From 0.33 `maintainers` and pool `members`
|
|
296
|
+
replace `identity.connectorAccess` and every `grant`, and maintainers replace
|
|
297
|
+
the four `identity` management permissions; delete them and the `identity`
|
|
298
|
+
section, and follow the package's `documentation/migration-0.33.md`. From 0.33 a stored token admits only once it is bound to a
|
|
299
|
+
declared agent: follow "Tokens issued before agents" above. See the package's
|
|
273
300
|
`documentation/auth.md` for the migration and storage requirements.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# cp .env.example .env
|
|
4
4
|
# docker compose build
|
|
5
|
-
# docker compose run --rm --no-deps connecta npm run --silent
|
|
5
|
+
# docker compose run --rm --no-deps connecta npm run --silent rotate-token -- local-machine
|
|
6
6
|
# docker compose up -d --build
|
|
7
7
|
#
|
|
8
8
|
# Compose reads `.env` from this directory, so one file configures both the
|
|
@@ -16,7 +16,7 @@ services:
|
|
|
16
16
|
ports:
|
|
17
17
|
- "${PORT:-8787}:${PORT:-8787}"
|
|
18
18
|
environment:
|
|
19
|
-
# accessTokens(storage) is always installed; an
|
|
19
|
+
# accessTokens(storage) is always installed; an agent with no issued token is closed.
|
|
20
20
|
# CONNECTA_TOKEN belongs to clients and is never configured on this server.
|
|
21
21
|
PORT: ${PORT:-8787}
|
|
22
22
|
# Downstream OAuth calls back to this origin. Unset is fine until this
|
|
@@ -28,6 +28,7 @@ services:
|
|
|
28
28
|
# on when set and off when empty.
|
|
29
29
|
CLERK_PUBLISHABLE_KEY: ${CLERK_PUBLISHABLE_KEY:-}
|
|
30
30
|
CLERK_SECRET_KEY: ${CLERK_SECRET_KEY:-}
|
|
31
|
+
CONNECTA_MAINTAINERS: ${CONNECTA_MAINTAINERS:-}
|
|
31
32
|
CONNECTA_CREDENTIAL_KEY: ${CONNECTA_CREDENTIAL_KEY:-}
|
|
32
33
|
CONNECTA_ACTIVITY: ${CONNECTA_ACTIVITY:-}
|
|
33
34
|
volumes:
|
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
"esbuild@0.28.2": true
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"
|
|
14
|
-
"
|
|
13
|
+
"adopt-token": "tsx src/adopt-token.ts",
|
|
14
|
+
"doctor": "connecta doctor --pool local-machine",
|
|
15
|
+
"rotate-token": "tsx src/rotate-token.ts",
|
|
15
16
|
"start": "tsx src/index.ts",
|
|
16
17
|
"typecheck": "tsc --noEmit"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"@clerk/backend": "^3.12.0",
|
|
20
|
-
"@zackbart/connecta": "0.
|
|
21
|
+
"@zackbart/connecta": "0.33.0",
|
|
21
22
|
"quickjs-emscripten": "0.32.0"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted one-time migration: bind a machine token issued before agents to a
|
|
3
|
+
* declared agent, so that machine's existing cta_ secret keeps working. Run
|
|
4
|
+
* with no arguments to list the tokens that can be adopted. A token binds
|
|
5
|
+
* once, only to an agent that has never been issued one; human-bound tokens
|
|
6
|
+
* are refused and stop admitting.
|
|
7
|
+
*/
|
|
8
|
+
import { AccessTokenManager } from "@zackbart/connecta/auth/access-tokens";
|
|
9
|
+
import connectaConfig from "./connecta.config.js";
|
|
10
|
+
|
|
11
|
+
const [tokenId, agent] = process.argv.slice(2);
|
|
12
|
+
const { storage, agents } = connectaConfig(process.env);
|
|
13
|
+
const manager = new AccessTokenManager(storage!, { agents: agents ?? [] });
|
|
14
|
+
if (tokenId === undefined) {
|
|
15
|
+
for (const token of await manager.unboundTokens()) {
|
|
16
|
+
process.stdout.write(`${token.id} ${token.createdAt} ${token.name}\n`);
|
|
17
|
+
}
|
|
18
|
+
} else if (!agent || process.argv.length !== 4) {
|
|
19
|
+
throw new Error("Usage: npm run adopt-token -- [<token-id> <agent>]");
|
|
20
|
+
} else {
|
|
21
|
+
await manager.adopt(tokenId, agent);
|
|
22
|
+
process.stdout.write(`${agent} now uses token ${tokenId}\n`);
|
|
23
|
+
}
|
|
@@ -25,6 +25,7 @@ export interface Env {
|
|
|
25
25
|
CONNECTA_DATABASE?: string;
|
|
26
26
|
CLERK_PUBLISHABLE_KEY?: string;
|
|
27
27
|
CLERK_SECRET_KEY?: string;
|
|
28
|
+
CONNECTA_MAINTAINERS?: string;
|
|
28
29
|
CONNECTA_CREDENTIAL_KEY?: string;
|
|
29
30
|
CONNECTA_ACTIVITY?: string;
|
|
30
31
|
}
|
|
@@ -68,22 +69,42 @@ export default defineConfig((env: Env) => {
|
|
|
68
69
|
return {
|
|
69
70
|
storage,
|
|
70
71
|
publicUrl,
|
|
72
|
+
// Required: can /mcp write? false lets call_destructive_tool and programs
|
|
73
|
+
// write, with the MCP client approving; true leaves write tools out of
|
|
74
|
+
// search and describe and refuses every write call. Pools inherit it
|
|
75
|
+
// unless they set their own readOnly. Startup fails without it.
|
|
76
|
+
readOnly: false,
|
|
71
77
|
// Required: model-written programs run in a bounded QuickJS child.
|
|
72
78
|
executor: quickJsExecutor(),
|
|
73
79
|
auth: clerk ? [clerk] : [],
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
80
|
+
// Required with Clerk: the Clerk user ids (comma-separated in
|
|
81
|
+
// CONNECTA_MAINTAINERS) who use plain /mcp, which serves every connector,
|
|
82
|
+
// and the operator UI. They alone administer shared credentials, manage
|
|
83
|
+
// agent tokens, and read activity. Everyone else uses a pool that lists
|
|
84
|
+
// them. Agents are never maintainers.
|
|
85
|
+
maintainers: clerk
|
|
86
|
+
? (set("CONNECTA_MAINTAINERS") ?? "")
|
|
87
|
+
.split(",")
|
|
88
|
+
.map((id) => id.trim())
|
|
89
|
+
.filter(Boolean)
|
|
90
|
+
: [],
|
|
91
|
+
// Each pool serves exactly its tools to its members: Clerk user ids at
|
|
92
|
+
// /mcp/<name>, and "agent:<name>" for a declared agent at /agent/<name>.
|
|
93
|
+
// A member connects their own account on the pool's personal connectors.
|
|
94
|
+
// `npm run doctor` checks /agent/local-machine with its token. The starter
|
|
95
|
+
// pool is the agent's base pool (shared connectors, no owner), named after
|
|
96
|
+
// the agent as the agent pool layout requires.
|
|
97
|
+
pools: { "local-machine": { tools: ["time"], members: ["agent:local-machine"] } },
|
|
98
|
+
// Machine clients are agents declared here by name, each with one cta_
|
|
99
|
+
// token. Issue or rotate one locally with
|
|
100
|
+
// `npm run --silent rotate-token -- local-machine`, or as a signed-in
|
|
101
|
+
// maintainer from the operator UI. Removing a name stops its token on the
|
|
102
|
+
// next request.
|
|
103
|
+
agents: ["local-machine"],
|
|
104
|
+
// Always installed: a slot with no issued token refuses every request.
|
|
105
|
+
// Tokens from before agents stop admitting until `npm run adopt-token`
|
|
106
|
+
// binds each machine's token to an agent; human-bound tokens never do.
|
|
78
107
|
accessTokens: accessTokens(storage),
|
|
79
|
-
// Connection management permissions default to none, so the template
|
|
80
|
-
// grants them. Split members from operators with `connectorAccess`,
|
|
81
|
-
// `activityAccess`, and `accessTokenManagement`, each derived from the
|
|
82
|
-
// authenticated identity and never from an MCP argument.
|
|
83
|
-
identity: {
|
|
84
|
-
credentialAdministration: () => "all",
|
|
85
|
-
personalConnection: () => "all",
|
|
86
|
-
},
|
|
87
108
|
vault: credentialKey ? encryptedCredentialVault(storage, credentialKey) : undefined,
|
|
88
109
|
// Payload-free activity history at /activity: who called what, when, how
|
|
89
110
|
// long it took, and whether it worked. Each write prunes rows older than
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted local provisioning: issue or rotate one declared agent's token
|
|
3
|
+
* against the same configuration and database the server uses. The previous
|
|
4
|
+
* secret stops working on its next request.
|
|
5
|
+
*/
|
|
6
|
+
import { AccessTokenManager } from "@zackbart/connecta/auth/access-tokens";
|
|
7
|
+
import connectaConfig from "./connecta.config.js";
|
|
8
|
+
|
|
9
|
+
const agent = process.argv[2];
|
|
10
|
+
if (!agent || process.argv.length !== 3) {
|
|
11
|
+
throw new Error("Usage: npm run --silent rotate-token -- <agent>");
|
|
12
|
+
}
|
|
13
|
+
const { storage, agents } = connectaConfig(process.env);
|
|
14
|
+
const manager = new AccessTokenManager(storage!, { agents: agents ?? [] });
|
|
15
|
+
const { token } = await manager.rotate(agent, "local-provisioning");
|
|
16
|
+
// The secret is returned once. Keep stdout private; storage holds its hash.
|
|
17
|
+
process.stdout.write(`${token}\n`);
|
package/dist/tool-safety.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ToolDef, ToolVerdict } from "./types.js";
|
|
2
|
-
export type PoolTrust = "trusted" | "read-only";
|
|
3
|
-
/** Deployment override, then verified provider review, then fail-closed hints. */
|
|
4
|
-
export declare function classifyTool(definition: ToolDef, override?: "read" | "write", review?: {
|
|
5
|
-
verdict: ToolVerdict;
|
|
6
|
-
stale?: boolean;
|
|
7
|
-
}): "read" | "write";
|
|
8
|
-
/** The only permission decision for a connector call. Approval is host-owned. */
|
|
9
|
-
export declare function surfaceAllowsTool(classification: ToolDef["classification"], surface: string, trust?: PoolTrust): boolean;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/** Trusted local provisioning against the same database the server uses. */
|
|
2
|
-
import { AccessTokenManager } from "@zackbart/connecta/auth/access-tokens";
|
|
3
|
-
import { openSqlite, sqliteStorage } from "@zackbart/connecta/sqlite";
|
|
4
|
-
|
|
5
|
-
const name = process.argv[2];
|
|
6
|
-
if (!name || process.argv.length !== 3) {
|
|
7
|
-
throw new Error('Usage: npm run provision-token -- "machine-name"');
|
|
8
|
-
}
|
|
9
|
-
const database = openSqlite(process.env.CONNECTA_DATABASE || "./.connecta.sqlite");
|
|
10
|
-
try {
|
|
11
|
-
const manager = new AccessTokenManager(sqliteStorage(database));
|
|
12
|
-
const { token } = await manager.create(name, "local-provisioning");
|
|
13
|
-
// The secret is returned once. Keep stdout private; storage holds its hash.
|
|
14
|
-
process.stdout.write(`${token}\n`);
|
|
15
|
-
} finally {
|
|
16
|
-
database.close();
|
|
17
|
-
}
|