@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
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,7 +140,7 @@ 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
|
|
|
@@ -144,7 +163,10 @@ Connection management needs an interactive identity. A machine access token
|
|
|
144
163
|
never authorizes browser credential mutations. `@clerk/backend`
|
|
145
164
|
ships as a dependency of this template. To enable Clerk, set both
|
|
146
165
|
`CLERK_PUBLISHABLE_KEY` and `CLERK_SECRET_KEY` (one without the other refuses to
|
|
147
|
-
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`.
|
|
148
170
|
Enable `aud_claim_enabled: true` in Clerk's instance OAuth application settings
|
|
149
171
|
(`PATCH /v1/instance/oauth_application_settings` in Clerk's Backend API), then
|
|
150
172
|
read the setting back. Both JWT and opaque OAuth tokens are supported.
|
|
@@ -164,18 +186,20 @@ audience. New DCR registrations need new entries, so prefer audience binding
|
|
|
164
186
|
for standard host onboarding. Clerk session tokens work only on operator
|
|
165
187
|
routes. [Inbound auth](https://github.com/zackbart/connecta/blob/main/documentation/auth.md#clerk-oauth-tokens-and-operator-sessions)
|
|
166
188
|
explains configuration, verification, and fixed rejection reason codes.
|
|
167
|
-
Machine clients
|
|
168
|
-
through `accessTokens(storage)`, which `src/connecta.config.ts`
|
|
169
|
-
the database.
|
|
170
|
-
|
|
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
|
|
171
193
|
Clerk and never requires opening the server.
|
|
172
194
|
|
|
173
|
-
Set
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
`
|
|
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.
|
|
179
203
|
|
|
180
204
|
### Credential vault
|
|
181
205
|
|
|
@@ -220,7 +244,7 @@ Diagnostics are independent. Keep the default logger or provide your own;
|
|
|
220
244
|
|
|
221
245
|
The UI displays connections and current permissions. Configuration still owns
|
|
222
246
|
the connector set, tool definitions, and access rules. Access token management
|
|
223
|
-
requires
|
|
247
|
+
requires a signed-in Clerk maintainer. There is no team roster or policy editor.
|
|
224
248
|
|
|
225
249
|
## Deployment contract
|
|
226
250
|
|
|
@@ -268,8 +292,9 @@ feature should not leave a tab behind.
|
|
|
268
292
|
Upgrading from v0.23 does not require rotating managed `cta_…` tokens. Import
|
|
269
293
|
`accessTokens` from `@zackbart/connecta/auth/access-tokens`, replace the old
|
|
270
294
|
`accessTokens: true` with `accessTokens: accessTokens(storage)`, and keep the
|
|
271
|
-
same persistent storage namespace and
|
|
272
|
-
`identity.
|
|
273
|
-
|
|
274
|
-
|
|
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
|
|
275
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
|
}
|
|
@@ -76,19 +77,34 @@ export default defineConfig((env: Env) => {
|
|
|
76
77
|
// Required: model-written programs run in a bounded QuickJS child.
|
|
77
78
|
executor: quickJsExecutor(),
|
|
78
79
|
auth: clerk ? [clerk] : [],
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
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.
|
|
83
107
|
accessTokens: accessTokens(storage),
|
|
84
|
-
// Connection management permissions default to none, so the template
|
|
85
|
-
// grants them. Split members from operators with `connectorAccess`,
|
|
86
|
-
// `activityAccess`, and `accessTokenManagement`, each derived from the
|
|
87
|
-
// authenticated identity and never from an MCP argument.
|
|
88
|
-
identity: {
|
|
89
|
-
credentialAdministration: () => "all",
|
|
90
|
-
personalConnection: () => "all",
|
|
91
|
-
},
|
|
92
108
|
vault: credentialKey ? encryptedCredentialVault(storage, credentialKey) : undefined,
|
|
93
109
|
// Payload-free activity history at /activity: who called what, when, how
|
|
94
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`);
|
|
@@ -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
|
-
}
|