@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/dist/routes/ui-data.js
CHANGED
|
@@ -137,8 +137,8 @@ export function uiData(registry, baseUrl, options) {
|
|
|
137
137
|
const fields = credentialFields();
|
|
138
138
|
return Effect.succeed({
|
|
139
139
|
...card,
|
|
140
|
-
...(fields?.length ? { fields } : {}),
|
|
141
|
-
configured:
|
|
140
|
+
...(fields?.length ? { fields: fields.map((field) => ({ ...field, configured: null })) } : {}),
|
|
141
|
+
configured: null,
|
|
142
142
|
removable: true,
|
|
143
143
|
testable: testRule.mode !== null,
|
|
144
144
|
error: "Stored credential could not be read.",
|
package/dist/routes/ui.js
CHANGED
|
@@ -9,7 +9,7 @@ import { CONNECTA_VERSION } from "../version.js";
|
|
|
9
9
|
import { CONNECTA_FAVICON_ICO } from "../favicon.js";
|
|
10
10
|
import { CONNECTA_FAVICON_SVG, operatorPageForPath, renderUiHtml } from "../ui.js";
|
|
11
11
|
import { authorized, refuse, scopeFor, serveOperator, visibleRegistry, } from "./operator.js";
|
|
12
|
-
import { mayManageConnector, privateJson } from "./shared.js";
|
|
12
|
+
import { managesAgentTokens, mayManageConnector, privateJson, readsActivity } from "./shared.js";
|
|
13
13
|
import { routeUiConfig } from "./ui-config.js";
|
|
14
14
|
import { uiData } from "./ui-data.js";
|
|
15
15
|
/**
|
|
@@ -84,7 +84,8 @@ export async function routeUi(context) {
|
|
|
84
84
|
? opts.config.auth.find((provider) => provider.uiAuth?.kind === "cloudflare-access")?.uiAuth
|
|
85
85
|
: undefined;
|
|
86
86
|
const uiAuth = ambient ??
|
|
87
|
-
opts.config.auth.find((provider) => provider.uiAuth && provider.uiAuth.kind !== "cloudflare-access")?.uiAuth
|
|
87
|
+
opts.config.auth.find((provider) => provider.uiAuth && provider.uiAuth.kind !== "cloudflare-access")?.uiAuth ??
|
|
88
|
+
opts.config.auth.find((provider) => provider.uiAuth?.kind === "cloudflare-access")?.uiAuth;
|
|
88
89
|
const mcpUrl = new URL("/mcp", baseUrl).toString();
|
|
89
90
|
const clerkOrigin = uiAuth?.kind === "clerk" && isSafeHttpsUrl(uiAuth.frontendApiUrl)
|
|
90
91
|
? new URL(uiAuth.frontendApiUrl).origin
|
|
@@ -115,14 +116,14 @@ function operatorView({ opts }, authz, registry) {
|
|
|
115
116
|
const visible = registry.listConnectors();
|
|
116
117
|
const mayManage = (id) => {
|
|
117
118
|
const connector = registry.getConnector(id);
|
|
118
|
-
return Boolean(connector && mayManageConnector(authz, connector));
|
|
119
|
+
return Boolean(connector && mayManageConnector(opts, authz, connector));
|
|
119
120
|
};
|
|
120
121
|
const permissions = (connector) => ({
|
|
121
122
|
use: true,
|
|
122
123
|
manageSharedAuth: connector.authScope !== "personal" && mayManage(connector.id),
|
|
123
124
|
connectPersonal: connector.authScope === "personal" && mayManage(connector.id),
|
|
124
125
|
});
|
|
125
|
-
const activityEnabled = Boolean(opts.config.activity?.store.list) && authz
|
|
126
|
+
const activityEnabled = Boolean(opts.config.activity?.store.list) && readsActivity(opts, authz);
|
|
126
127
|
const credentialManagement = visible.some((c) => c.credential && mayManage(c.id))
|
|
127
128
|
? opts.config.vault
|
|
128
129
|
? "available"
|
|
@@ -169,17 +170,9 @@ function summary(context) {
|
|
|
169
170
|
const authz = yield* authorized(context);
|
|
170
171
|
const registry = yield* visibleRegistry(context, authz);
|
|
171
172
|
const { visible, mayManage, permissions, activityEnabled, credentialManagement } = operatorView(context, authz, registry);
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
const pools = [];
|
|
176
|
-
for (const [name, pool] of opts.pools ?? []) {
|
|
177
|
-
const granted = yield* Effect.tryPromise(async () => (await pool.grant(authz.identity)) === true).pipe(
|
|
178
|
-
// A throwing grant is a refusal at the endpoint, and so a refusal here.
|
|
179
|
-
Effect.orElseSucceed(() => false));
|
|
180
|
-
if (granted)
|
|
181
|
-
pools.push(name);
|
|
182
|
-
}
|
|
173
|
+
// Only maintainers reach here (#837); setup commands are offered for every
|
|
174
|
+
// declared pool, since they administer them all.
|
|
175
|
+
const pools = [...opts.pools.keys()];
|
|
183
176
|
return privateJson({
|
|
184
177
|
...(pools.length ? { pools } : {}),
|
|
185
178
|
serverInfo: opts.config.serverInfo,
|
|
@@ -187,7 +180,7 @@ function summary(context) {
|
|
|
187
180
|
activityEnabled,
|
|
188
181
|
...(opts.config.accessTokens
|
|
189
182
|
? {
|
|
190
|
-
accessTokenManagement:
|
|
183
|
+
accessTokenManagement: managesAgentTokens(opts, authz) ? "available" : "requires_operator",
|
|
191
184
|
}
|
|
192
185
|
: {}),
|
|
193
186
|
credentialManagement,
|
|
@@ -12,6 +12,15 @@
|
|
|
12
12
|
// shared queue between them was refused.
|
|
13
13
|
import { Effect } from "effect";
|
|
14
14
|
let program;
|
|
15
|
+
const budgetCharges = new WeakMap();
|
|
16
|
+
/** Bind budget-only admission to the partition already owned by this permit. */
|
|
17
|
+
export function provideCallBudgetCharge(permit, charge) {
|
|
18
|
+
budgetCharges.set(permit, charge);
|
|
19
|
+
}
|
|
20
|
+
/** Charge an internal request without acquiring another concurrency permit. */
|
|
21
|
+
export function chargeCallBudget(permit, signal) {
|
|
22
|
+
return Effect.clockWith((clock) => budgetCharges.get(permit)?.(clock.currentTimeMillisUnsafe(), signal) ?? Effect.void);
|
|
23
|
+
}
|
|
15
24
|
// What the live Clock reads, looked up on every call rather than bound once,
|
|
16
25
|
// so a Date faked after a caller queued (vitest's setSystemTime) still counts.
|
|
17
26
|
const liveNow = () => Date.now();
|
package/dist/server.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Effect } from "effect";
|
|
|
2
2
|
import { notFoundResponse } from "./branding.js";
|
|
3
3
|
import { aggregateCallAdmissionSnapshots } from "./call-admission.js";
|
|
4
4
|
import { isAdmittingExecutor } from "./executor-admission.js";
|
|
5
|
+
import { isAgentPath } from "./routes/agent-path.js";
|
|
5
6
|
import { createMcpRoute, MCP_CORS_HEADERS } from "./routes/mcp.js";
|
|
6
7
|
import { routeOAuthCallback } from "./routes/oauth.js";
|
|
7
8
|
import { routeOAuthClientMetadata } from "./routes/oauth-client-metadata.js";
|
|
@@ -59,6 +60,10 @@ export function createFetchHandler(opts) {
|
|
|
59
60
|
};
|
|
60
61
|
const route = (context) => Effect.gen(function* () {
|
|
61
62
|
const { request, path, baseUrl } = context;
|
|
63
|
+
// The agent namespace is routed before anything else, so no path
|
|
64
|
+
// Cloudflare Access bypasses as `/agent/*` can reach a human route.
|
|
65
|
+
if (isAgentPath(path))
|
|
66
|
+
return (yield* routeMcp.handle(context)) ?? notFoundResponse(request, opts.config);
|
|
62
67
|
const clientMetadata = routeOAuthClientMetadata(context);
|
|
63
68
|
if (clientMetadata)
|
|
64
69
|
return clientMetadata;
|
package/dist/storage/keys.js
CHANGED
|
@@ -164,7 +164,12 @@ export const oauthHandoffKeys = {
|
|
|
164
164
|
},
|
|
165
165
|
handoff: (connectorId, stateHash) => validateStorageKey(`oauth-handoff:v1:${connectorId}:${stateHash}`),
|
|
166
166
|
};
|
|
167
|
-
/**
|
|
167
|
+
/**
|
|
168
|
+
* Connecta-issued `cta_` access tokens: token records, digest lookups, one
|
|
169
|
+
* slot per declared agent naming its live record, and a never-deleted claim per
|
|
170
|
+
* legacy record an adoption has taken. `active` is the capacity
|
|
171
|
+
* ledger releases before 0.33 wrote; nothing writes it now.
|
|
172
|
+
*/
|
|
168
173
|
export const accessTokenKeys = {
|
|
169
174
|
family: {
|
|
170
175
|
name: "access-token",
|
|
@@ -178,6 +183,9 @@ export const accessTokenKeys = {
|
|
|
178
183
|
recordPrefix: "access-token:v1:record:",
|
|
179
184
|
record: (id) => validateStorageKey(`access-token:v1:record:${id}`),
|
|
180
185
|
lookup: (tokenHash) => validateStorageKey(`access-token:v1:lookup:${tokenHash}`),
|
|
186
|
+
agent: (name) => validateStorageKey(`access-token:v1:agent:${name}`),
|
|
187
|
+
/** Write-once claim that a legacy token record has been taken by one agent's adoption. */
|
|
188
|
+
adopted: (legacyRecordId) => validateStorageKey(`access-token:v1:adopted:${legacyRecordId}`),
|
|
181
189
|
active: "access-token:v1:active",
|
|
182
190
|
};
|
|
183
191
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -727,6 +727,11 @@ export type AuthResult = {
|
|
|
727
727
|
sessionCookies?: readonly string[];
|
|
728
728
|
/** Human owner represented by a non-interactive access credential. */
|
|
729
729
|
principal?: IdentityReference;
|
|
730
|
+
/**
|
|
731
|
+
* Declared agent name. Only the built-in `accessTokens()` adapter may
|
|
732
|
+
* set it; a result from any other provider that carries it is refused.
|
|
733
|
+
*/
|
|
734
|
+
agent?: string;
|
|
730
735
|
} | {
|
|
731
736
|
ok: false;
|
|
732
737
|
response: Response;
|
|
@@ -747,6 +752,12 @@ export interface AuthenticatedIdentity {
|
|
|
747
752
|
subject?: IdentityReference;
|
|
748
753
|
/** Human owner of personal connector authentication. */
|
|
749
754
|
principal?: IdentityReference;
|
|
755
|
+
/**
|
|
756
|
+
* Name of the code-declared agent this caller is, from `agents`. Set only
|
|
757
|
+
* when the built-in access-token adapter admitted a `cta_` token bound to
|
|
758
|
+
* a currently declared agent; an agent never has a `principal`.
|
|
759
|
+
*/
|
|
760
|
+
agent?: string;
|
|
750
761
|
interactive: boolean;
|
|
751
762
|
}
|
|
752
763
|
/** Public browser-auth configuration exposed to connecta's status UI. */
|
package/dist/ui.d.ts
CHANGED
|
@@ -49,4 +49,4 @@ _nonce?: string, page?: OperatorPage): string;
|
|
|
49
49
|
export declare function operatorUi(options?: {
|
|
50
50
|
branding?: ConnectaBranding;
|
|
51
51
|
}): OperatorSurface;
|
|
52
|
-
export type { OperatorUiContract,
|
|
52
|
+
export type { OperatorUiContract, OperatorUiContractV2, OperatorRole, OperatorMember, OperatorPoolV2, OperatorRootEndpoint, OperatorMemberConnector, OperatorMemberManage, OperatorAgent, OperatorSharedSource, OperatorRunsAs, OperatorConnectorPoolCell, OperatorConnectorOverlay, OperatorTool, OperatorGrant, OperatorLastCall, } from "./operator-ui/contract.js";
|
package/dist/ui.js
CHANGED
|
@@ -4,33 +4,31 @@ import { routeCredentials } from "./routes/credentials.js";
|
|
|
4
4
|
import { routeOAuthManagement } from "./routes/oauth-management.js";
|
|
5
5
|
import { uiData } from "./routes/ui-data.js";
|
|
6
6
|
import { runEdge } from "./runtime/run.js";
|
|
7
|
-
import { OPERATOR_UI_STYLE_PATH, OPERATOR_UI_SCRIPT_PATH, OPERATOR_UI_NOTICES_PATH } from "./operator-ui/generated.js";
|
|
7
|
+
import { OPERATOR_UI_STYLE_PATH, OPERATOR_UI_SCHEME_PATH, OPERATOR_UI_SCRIPT_PATH, OPERATOR_UI_NOTICES_PATH, } from "./operator-ui/generated.js";
|
|
8
8
|
export { filterUiConnectors, } from "./operator-ui/model.js";
|
|
9
9
|
import { escapeHtml, isSafeHttpsUrl, renderPage, resolveBranding } from "./branding.js";
|
|
10
10
|
export { CONNECTA_FAVICON_SVG, resolveBranding, isSafeHttpUrl, isSafeHttpsUrl, isSafeIconHref } from "./branding.js";
|
|
11
11
|
const OPERATOR_PAGE_LABELS = {
|
|
12
|
-
|
|
12
|
+
endpoints: "Endpoints",
|
|
13
13
|
connections: "Connectors",
|
|
14
14
|
connector: "Connector",
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
config: "Config",
|
|
18
|
-
tokens: "Access tokens",
|
|
15
|
+
settings: "Settings",
|
|
16
|
+
tokens: "Tokens",
|
|
19
17
|
activity: "Activity",
|
|
20
18
|
};
|
|
21
19
|
export function operatorPageForPath(path) {
|
|
22
20
|
if (path === "/")
|
|
23
|
-
return "
|
|
21
|
+
return "endpoints";
|
|
24
22
|
if (path === "/connectors")
|
|
25
23
|
return "connections";
|
|
26
24
|
if (/^\/connectors\/[a-z0-9_-]+$/.test(path))
|
|
27
25
|
return "connector";
|
|
28
26
|
if (path === "/tools")
|
|
29
|
-
return "
|
|
27
|
+
return "connections";
|
|
30
28
|
if (path === "/access")
|
|
31
|
-
return "
|
|
32
|
-
if (path === "/config")
|
|
33
|
-
return "
|
|
29
|
+
return "endpoints";
|
|
30
|
+
if (path === "/config" || path === "/settings")
|
|
31
|
+
return "settings";
|
|
34
32
|
if (path === "/tokens")
|
|
35
33
|
return "tokens";
|
|
36
34
|
if (path === "/activity")
|
|
@@ -101,7 +99,7 @@ function jsonForInlineScript(value) {
|
|
|
101
99
|
*/
|
|
102
100
|
export function renderUiHtml(uiAuth, mcpUrl = "/mcp", branding,
|
|
103
101
|
/** @deprecated Scripts load from same-origin assets; ignored. */
|
|
104
|
-
_nonce, page = "
|
|
102
|
+
_nonce, page = "endpoints") {
|
|
105
103
|
const clerk = uiAuth?.kind === "clerk" ? uiAuth : undefined;
|
|
106
104
|
// The Clerk loader's origin. A value that fails the gate is dropped rather
|
|
107
105
|
// than escaped into the page: the loader tag is simply not emitted, the gate
|
|
@@ -130,13 +128,15 @@ _nonce, page = "overview") {
|
|
|
130
128
|
: "";
|
|
131
129
|
// The shared layout owns the head, scheme, theme, and masthead; the shell
|
|
132
130
|
// adds its own bundle (which already imports the shared tokens), the nav
|
|
133
|
-
// mount, and the app.
|
|
131
|
+
// mount, and the app. The scheme initializer blocks, ahead of the
|
|
132
|
+
// stylesheet, so a saved color scheme holds from the first paint.
|
|
134
133
|
return renderPage(branding, {
|
|
135
134
|
title: operatorPageTitle(page, brand.pageTitle),
|
|
136
135
|
uiMounted: true,
|
|
137
136
|
operatorShell: true,
|
|
138
137
|
styles: "",
|
|
139
|
-
head: `<
|
|
138
|
+
head: `<script src="${OPERATOR_UI_SCHEME_PATH}"></script>` +
|
|
139
|
+
`<link rel="stylesheet" href="${OPERATOR_UI_STYLE_PATH}"><link rel="license" href="${OPERATOR_UI_NOTICES_PATH}">` +
|
|
140
140
|
clerkScript,
|
|
141
141
|
skipTo: { id: "operatorContent", label: "Skip to operator page" },
|
|
142
142
|
mastheadEnd: '<div id="operatorNav"></div>',
|
|
@@ -156,6 +156,7 @@ _nonce, page = "overview") {
|
|
|
156
156
|
auth,
|
|
157
157
|
mcpUrl,
|
|
158
158
|
initialPage: page,
|
|
159
|
+
schemePinned: brand.theme.colorScheme !== "system",
|
|
159
160
|
titleSuffix: brand.pageTitle,
|
|
160
161
|
productName: brand.productName,
|
|
161
162
|
productDescription: brand.description,
|
|
@@ -186,6 +187,7 @@ export function operatorUi(options = {}) {
|
|
|
186
187
|
"/tools",
|
|
187
188
|
"/access",
|
|
188
189
|
"/config",
|
|
190
|
+
"/settings",
|
|
189
191
|
"/ui",
|
|
190
192
|
"/ui/*",
|
|
191
193
|
"/favicon.svg",
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CONNECTA_VERSION = "0.
|
|
1
|
+
export declare const CONNECTA_VERSION = "0.33.0";
|
package/dist/version.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// The one rule for a Google Workspace address, shared by the Workspace
|
|
2
|
+
// providers' fixed `subject` and a pool's `owner` (#837, decisions/0006), so
|
|
3
|
+
// config accepts exactly the addresses a delegated token can be minted for.
|
|
4
|
+
/** A plausible mailbox: one `@`, no whitespace or control characters. */
|
|
5
|
+
const ADDRESS = /^[^\s@<>()",;:\\[\]]+@[^\s@<>()",;:\\[\]]+\.[^\s@<>()",;:\\[\]]+$/;
|
|
6
|
+
/** Whether `value`, already trimmed, is a Workspace email address. */
|
|
7
|
+
export function isWorkspaceAddress(value) {
|
|
8
|
+
return typeof value === "string" && ADDRESS.test(value);
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Whose account a Google Workspace connector acts as, for the operator
|
|
2
|
+
// matrix (#837, decisions/0006). The Workspace providers tag the connector
|
|
3
|
+
// they build; nothing else can, and nothing a request sends reaches this.
|
|
4
|
+
// Read only by the operator contract, which never shows a mapping function.
|
|
5
|
+
const tagged = new WeakMap();
|
|
6
|
+
/** Tag a Workspace connector with its subject kind, returning it unchanged. */
|
|
7
|
+
export function tagWorkspaceSubject(connector, subject) {
|
|
8
|
+
tagged.set(connector, typeof subject === "string" ? { kind: "fixed", subject } : { kind: "mapping" });
|
|
9
|
+
return connector;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The subject kind of a tagged connector, or undefined for any other. Walks
|
|
13
|
+
* the prototype chain, since provider construction may wrap a connector it
|
|
14
|
+
* cannot restamp in an object that inherits from it.
|
|
15
|
+
*/
|
|
16
|
+
export function workspaceSubjectOf(connector) {
|
|
17
|
+
for (let current = connector; current; current = Object.getPrototypeOf(current)) {
|
|
18
|
+
const subject = tagged.get(current);
|
|
19
|
+
if (subject)
|
|
20
|
+
return subject;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
package/documentation/README.md
CHANGED
|
@@ -1,34 +1,58 @@
|
|
|
1
1
|
# Agent documentation
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Start here when operating a deployment installed with `@zackbart/connecta`.
|
|
4
|
+
All operator procedures below are available in the installed package; paths in
|
|
5
|
+
this directory are relative to `node_modules/@zackbart/connecta/documentation/`.
|
|
6
|
+
For an existing endpoint, start with [Operating an endpoint](./operating.md).
|
|
7
|
+
For a new deployment, start with [Deploying Connecta](./deploying.md).
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
| Add
|
|
12
|
-
|
|
|
9
|
+
## Operator tasks
|
|
10
|
+
|
|
11
|
+
| Task | Self-contained procedure |
|
|
12
|
+
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| Add or remove a connector | [Change the connector roster](./integrating.md#add-or-remove-a-connector) |
|
|
14
|
+
| Organize an agent's pools | [Organizing an agent's pools](./auth.md#organizing-an-agents-pools) |
|
|
15
|
+
| Add a person (maintainer or pool member) | [Add a person](./auth.md#add-a-person), [member page](./operator-ui.md#use-the-member-page) |
|
|
16
|
+
| Connect a shared credential | [Connect a shared credential](./auth.md#connect-a-shared-credential) |
|
|
17
|
+
| Issue, rotate, or revoke an agent token | [Manage an agent token](./auth.md#issue-rotate-or-revoke-an-agent-token) |
|
|
18
|
+
| Upgrade between versions | [Upgrade an existing deployment](./deploying.md#upgrade-an-existing-deployment), including [migration to 0.33](./migration-0.33.md) |
|
|
19
|
+
| Diagnose with `connecta doctor` | [Verify and diagnose](./deploying.md#verify-and-diagnose) |
|
|
20
|
+
|
|
21
|
+
## Audience rule
|
|
22
|
+
|
|
23
|
+
Shipped docs (`documentation/`, `templates/`, `examples/worker/`, and the root
|
|
24
|
+
`README.md`) are written first for an agent operating a deployment from the
|
|
25
|
+
installed package. Operator conventions must be self-contained rules plus a
|
|
26
|
+
neutral example. Decision records and issues explain why; no operator task
|
|
27
|
+
requires them, `spec/`, `.claude/`, or the Connecta source checkout. Those
|
|
28
|
+
three directories do not ship. Contributor source maps, INV citations, and
|
|
29
|
+
implementation/test evidence belong under clearly labeled contributor
|
|
30
|
+
headings and are optional for operators. Use `assistant`, `alice`, `bob`,
|
|
31
|
+
`crm`, `tickets`, `notes_alice`, and `alice@example.com` in examples; never
|
|
32
|
+
real deployment, client, person, or organization names. Maintained provider
|
|
33
|
+
product names stay.
|
|
13
34
|
|
|
14
35
|
## Contract reference
|
|
15
36
|
|
|
16
|
-
| Guide
|
|
17
|
-
|
|
|
18
|
-
| [Meta-tools](./meta-tools.md)
|
|
19
|
-
| [Code mode](./code-mode.md)
|
|
20
|
-
| [Auth](./auth.md)
|
|
21
|
-
| [Architecture](./architecture.md)
|
|
22
|
-
| [Operator UI](./operator-ui.md)
|
|
23
|
-
| [Operator UI tests](./operator-tests.md)
|
|
24
|
-
| [
|
|
25
|
-
| [Provider
|
|
37
|
+
| Guide | Owns |
|
|
38
|
+
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
39
|
+
| [Meta-tools](./meta-tools.md) | Six top-level tools, discovery, direct-call results, paging, skills, and recovery |
|
|
40
|
+
| [Code mode](./code-mode.md) | JavaScript guest API, executor requirements, output, retries, cancellation, limits, and writes |
|
|
41
|
+
| [Auth](./auth.md) | Inbound identity, maintainers, pools and members, agents, credential ownership, and downstream OAuth |
|
|
42
|
+
| [Architecture (contributor reference)](./architecture.md) | Request lifetimes, routes, storage, configuration, import boundaries, and Effect implementation |
|
|
43
|
+
| [Operator UI](./operator-ui.md) | Optional UI setup, scoped configuration and live-data contract, activity disclosure, and UI implementation |
|
|
44
|
+
| [Operator UI tests (contributor reference)](./operator-tests.md) | Browser state matrix, real-server flows, and snapshot maintenance |
|
|
45
|
+
| [Migration to 0.33](./migration-0.33.md) | Upgrade actions from 0.32 options to maintainers, members, agents, agent endpoints, and pool owners |
|
|
46
|
+
| [Provider migration for 0.29](./provider-migration-0.29.md) | Upgrade actions for Notion, Vercel, and Cloudflare; provider reconciliation tables supply exact name mappings |
|
|
47
|
+
| [Provider auth migration](./provider-auth-migration.md) | Upgrade actions when `auth` selects hosted MCP or Connecta's REST connector, Stripe and Vercel |
|
|
26
48
|
|
|
27
49
|
Each long contract starts with task routes. Follow those section links before
|
|
28
|
-
reading the whole guide.
|
|
29
|
-
|
|
50
|
+
reading the whole guide. Contributor references at the end are optional
|
|
51
|
+
implementation evidence.
|
|
52
|
+
|
|
53
|
+
## Contributor reference
|
|
30
54
|
|
|
31
|
-
|
|
55
|
+
### Documentation ownership
|
|
32
56
|
|
|
33
57
|
The root [README](../README.md) explains the product for people. It owns what
|
|
34
58
|
Connecta offers, how the pieces connect, deployment choices, and the setup
|