@zackbart/connecta 0.9.1 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/README.md +49 -92
  3. package/dist/access-tokens.d.ts +32 -0
  4. package/dist/access-tokens.d.ts.map +1 -0
  5. package/dist/access-tokens.js +225 -0
  6. package/dist/access-tokens.js.map +1 -0
  7. package/dist/catalog-service.d.ts.map +1 -1
  8. package/dist/catalog-service.js +1 -4
  9. package/dist/catalog-service.js.map +1 -1
  10. package/dist/errors.d.ts +5 -0
  11. package/dist/errors.d.ts.map +1 -1
  12. package/dist/errors.js +26 -0
  13. package/dist/errors.js.map +1 -1
  14. package/dist/execute.d.ts +3 -1
  15. package/dist/execute.d.ts.map +1 -1
  16. package/dist/execute.js +79 -18
  17. package/dist/execute.js.map +1 -1
  18. package/dist/executor-result.d.ts.map +1 -1
  19. package/dist/executor-result.js +37 -6
  20. package/dist/executor-result.js.map +1 -1
  21. package/dist/executors/quickjs-protocol.d.ts +12 -0
  22. package/dist/executors/quickjs-protocol.d.ts.map +1 -1
  23. package/dist/executors/quickjs-protocol.js +14 -0
  24. package/dist/executors/quickjs-protocol.js.map +1 -1
  25. package/dist/executors/quickjs-runtime.d.ts.map +1 -1
  26. package/dist/executors/quickjs-runtime.js +6 -3
  27. package/dist/executors/quickjs-runtime.js.map +1 -1
  28. package/dist/executors/quickjs.d.ts.map +1 -1
  29. package/dist/executors/quickjs.js +10 -4
  30. package/dist/executors/quickjs.js.map +1 -1
  31. package/dist/index.d.ts +27 -6
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +43 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/invocation.d.ts.map +1 -1
  36. package/dist/invocation.js +1 -4
  37. package/dist/invocation.js.map +1 -1
  38. package/dist/meta-tools.d.ts +26 -5
  39. package/dist/meta-tools.d.ts.map +1 -1
  40. package/dist/meta-tools.js +84 -40
  41. package/dist/meta-tools.js.map +1 -1
  42. package/dist/operator-ui/generated.d.ts +2 -2
  43. package/dist/operator-ui/generated.d.ts.map +1 -1
  44. package/dist/operator-ui/generated.js +2 -2
  45. package/dist/operator-ui/generated.js.map +1 -1
  46. package/dist/operator-ui/model.d.ts +2 -0
  47. package/dist/operator-ui/model.d.ts.map +1 -1
  48. package/dist/operator-ui/model.js.map +1 -1
  49. package/dist/routes/access-tokens.d.ts +7 -0
  50. package/dist/routes/access-tokens.d.ts.map +1 -0
  51. package/dist/routes/access-tokens.js +84 -0
  52. package/dist/routes/access-tokens.js.map +1 -0
  53. package/dist/routes/mcp.d.ts.map +1 -1
  54. package/dist/routes/mcp.js +8 -2
  55. package/dist/routes/mcp.js.map +1 -1
  56. package/dist/routes/shared.d.ts +11 -2
  57. package/dist/routes/shared.d.ts.map +1 -1
  58. package/dist/routes/shared.js.map +1 -1
  59. package/dist/routes/ui.d.ts.map +1 -1
  60. package/dist/routes/ui.js +9 -1
  61. package/dist/routes/ui.js.map +1 -1
  62. package/dist/server.d.ts.map +1 -1
  63. package/dist/server.js +5 -0
  64. package/dist/server.js.map +1 -1
  65. package/dist/skills.d.ts +15 -3
  66. package/dist/skills.d.ts.map +1 -1
  67. package/dist/skills.js +63 -10
  68. package/dist/skills.js.map +1 -1
  69. package/dist/storage/file.d.ts.map +1 -1
  70. package/dist/storage/file.js +5 -0
  71. package/dist/storage/file.js.map +1 -1
  72. package/dist/storage/memory.d.ts.map +1 -1
  73. package/dist/storage/memory.js +8 -0
  74. package/dist/storage/memory.js.map +1 -1
  75. package/dist/types.d.ts +19 -0
  76. package/dist/types.d.ts.map +1 -1
  77. package/dist/ui.d.ts +4 -4
  78. package/dist/ui.d.ts.map +1 -1
  79. package/dist/ui.js +44 -1
  80. package/dist/ui.js.map +1 -1
  81. package/dist/version.d.ts +1 -1
  82. package/dist/version.d.ts.map +1 -1
  83. package/dist/version.js +1 -1
  84. package/dist/version.js.map +1 -1
  85. package/package.json +2 -2
  86. package/src/access-tokens.ts +289 -0
  87. package/src/catalog-service.ts +1 -5
  88. package/src/errors.ts +28 -0
  89. package/src/execute.ts +123 -48
  90. package/src/executor-result.ts +50 -6
  91. package/src/executors/quickjs-protocol.ts +19 -0
  92. package/src/executors/quickjs-runtime.ts +6 -2
  93. package/src/executors/quickjs.ts +10 -3
  94. package/src/index.ts +85 -5
  95. package/src/invocation.ts +1 -5
  96. package/src/meta-tools.ts +116 -53
  97. package/src/operator-ui/browser.css +63 -0
  98. package/src/operator-ui/browser.ts +288 -2
  99. package/src/operator-ui/generated.ts +2 -2
  100. package/src/operator-ui/model.ts +6 -0
  101. package/src/routes/access-tokens.ts +115 -0
  102. package/src/routes/mcp.ts +8 -2
  103. package/src/routes/shared.ts +11 -1
  104. package/src/routes/ui.ts +9 -0
  105. package/src/server.ts +5 -0
  106. package/src/skills.ts +79 -9
  107. package/src/storage/file.ts +5 -0
  108. package/src/storage/memory.ts +8 -0
  109. package/src/types.ts +20 -0
  110. package/src/ui.ts +50 -1
  111. package/src/version.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,134 @@
2
2
 
3
3
  All notable changes to this package are documented here.
4
4
 
5
+ ## 0.10.1 — 2026-07-30
6
+
7
+ An inbound-auth escape hatch for MCP clients whose OAuth implementations do not
8
+ interoperate cleanly with a Connecta deployment. Eligible Clerk operators can
9
+ now issue named, revocable Bearer tokens from `/tokens`; each call is attributed
10
+ to the token's immutable identity while activity history resolves the current
11
+ friendly name. The secret is shown once, only a SHA-256 digest is stored, and a
12
+ token can authenticate MCP without gaining operator privileges. **Deployments
13
+ that do not set `accessTokens: {}` are unchanged.** Enabling it requires a
14
+ storage adapter with `list(prefix)` and a Clerk auth provider so token lifecycle
15
+ operations remain behind the human operator boundary.
16
+
17
+ ### Added
18
+
19
+ - **Managed MCP access tokens.** `accessTokens: {}` adds a Clerk-only operator
20
+ ledger for creating, naming, renaming, and revoking `cta_…` Bearer tokens.
21
+ `maxActive` defaults to 100 and can be configured from 1 through 1,000.
22
+ - **Token-attributed activity.** Calls authenticated by a managed token record
23
+ its immutable token ID and resolve the current friendly name when an eligible
24
+ operator reads activity. Revoked metadata remains as a tombstone so historical
25
+ attribution survives rotation.
26
+ - **Enumerable storage.** `KVStorage.list(prefix)` is available for durable
27
+ metadata ledgers, with implementations in the built-in memory and file
28
+ adapters and the Cloudflare Workers KV example.
29
+
30
+ ### Fixed
31
+
32
+ - **One-time secrets leave no reusable operator-UI state.** The plaintext token
33
+ disappears when it is dismissed, when the operator navigates away or signs
34
+ out, and before the document enters the browser back-forward cache. The create
35
+ form stays unavailable while a newly issued secret is waiting to be stored.
36
+
37
+ ## 0.10.0 — 2026-07-30
38
+
39
+ **Code-first is what a model sees.** A deployment with an executor now serves
40
+ seven meta-tools instead of ten: `list_connectors`, `describe_tools`, and
41
+ `batch_call` are no longer top-level tools, and their behavior lives in
42
+ `connecta.search`, `connecta.describe`, and `connecta.batch` inside a program.
43
+ Nothing became unreachable and no policy machinery changed — writes still cross
44
+ `call_destructive_tool`, and `call_tool` deliberately stays, because a single cold
45
+ call is measurably cheaper direct than through a program. What breaks is a client
46
+ that calls one of the three folded names against an executor-backed deployment:
47
+ it gets an unknown-tool error. The always-loaded instructions, the `skills`
48
+ guidance, and the routing sentences in `call_tool`, `search_tools`, `get_result`,
49
+ and `execute_code` are rewritten for that surface, which measures 19.6% smaller
50
+ serialized tool definitions (10,675B → 8,587B), correcting the exploration's ~32%
51
+ estimate. **An executor-free deployment can ignore all of it**: it serves the same
52
+ nine tools with the same descriptions and the same instructions as before, byte
53
+ for byte. `surface: "classic"` alongside an executor restores the ten-tool shape.
54
+
55
+ The default was flipped by owner decision for a single-operator deployment rather
56
+ than by the repeated per-model eval that [`ethos.md`](./ethos.md) had gated it on;
57
+ that row now records the decision and its reasoning, and
58
+ [`eval/code-first-gate`](./eval/code-first-gate/README.md) remains as measurement
59
+ with all three of its arms now real deployment shapes rather than harness
60
+ simulations.
61
+
62
+ The code-mode guest API is now specified rather than merely described:
63
+ [`documentation/code-mode.md`](./documentation/code-mode.md) states what a
64
+ program is promised — surface, addressing, error shapes, projection, retry,
65
+ cancellation, limits, activity — with clause identifiers the tests cite, and
66
+ names the QuickJS/Dynamic Worker divergences as documented exceptions instead of
67
+ leaving them to be discovered. Both executors now run the same contract case
68
+ table, the Workers arm against a real Dynamic Worker in workerd. Writing the
69
+ clauses down turned up four places where the code did not quite match the
70
+ behavior worth having; those are the changes below, all additive or corrective,
71
+ and one of them (retryable policy refusals) reaches `call_tool` and `batch_call`
72
+ as well as programs.
73
+
74
+ ### Changed
75
+
76
+ - **The code-first surface is the default wherever an executor is configured.**
77
+ Seven tools: `execute_code`, `search_tools`, `call_tool`,
78
+ `call_destructive_tool`, `authorize_connector`, `get_result`, `skills`. Four
79
+ overlapping ways to reach one connector became two — `search_tools` then
80
+ `call_tool` for a single cold read, one `execute_code` run for everything wider.
81
+ An executor-free deployment is unchanged.
82
+ - **`ConnectaConfig.surface`** overrides what the executor implies. The reason to
83
+ set it is `"classic"` beside an executor, which is the ten-tool shape the eval
84
+ gate's incremental arm measures. `"code-first"` without an executor throws at
85
+ construction rather than advertise a program surface that does not exist, as
86
+ does any other value.
87
+ - **The eval gate configures its arms instead of faking one.** `gate-server.ts`
88
+ no longer filters `tools/list` or rewrites connecta's descriptions: all three
89
+ arms are ordinary deployments, so the harness measures the product and the arms
90
+ are byte-for-byte identical in the transport layer.
91
+
92
+ ### Added
93
+
94
+ - **Typed failures inside `connecta.batch`.** A failed call now reports
95
+ `{ address, ok: false, error, errorDetails }`, where `errorDetails` is the
96
+ same typed object `batch_call` returns (`code`, `retryable`, `retryAfterMs`,
97
+ and the `auth_required` recovery envelope). A thrown host error crosses the
98
+ sandbox bridge as a bare message in every executor, so this is the one channel
99
+ through which a program can tell a policy refusal from a transient failure
100
+ instead of cheerfully retrying the refusal. Programs reading `error` are
101
+ unaffected. An entry connecta could not even attempt — a malformed call object
102
+ — reports `batch_call_failed`, the code `batch_call` already uses for the same
103
+ situation.
104
+
105
+ ### Fixed
106
+
107
+ - **A policy refusal can no longer look retryable.** `unknown_address`,
108
+ `unknown_tool`, `ambiguous_tool_alias`, and
109
+ `destructive_tool_requires_approval` now pin `retryable: false` instead of
110
+ deriving it from their own message text. Those messages embed the address the
111
+ caller asked for, and the heuristic that classifies connector errors matches
112
+ `503`, `429`, and `temporar`, so a connector named `svc-503` or
113
+ `temporary-export` turned a refusal that will never succeed into one an agent
114
+ was told to retry. This affects `call_tool` and `batch_call` too, not only
115
+ programs.
116
+ - **An uncaught discovery-bound failure inside a program is typed.** A bad
117
+ `limit`, an oversized `addresses` list, or a discovery page over the
118
+ 256,000-byte ceiling now reaches the model as `invalid_args` or
119
+ `result_too_large` with `retryable: false`, the same envelope a failed tool
120
+ call gets, instead of as untyped error prose.
121
+ - **Bridge-limit errors name the address, not the plumbing.** A host call over
122
+ the QuickJS 256 KiB bound reported `connecta.__callNamespace` — the internal
123
+ dispatcher every shortcut namespace shares — where it now reports the
124
+ `connector.tool` address the program called.
125
+ - **An oversized program result is truncated once.** The over-cap notice is now
126
+ sized so its *serialized* form fits the 24,000-character result cap.
127
+ Previously the QuickJS path truncated in the child and again in the parent, so
128
+ a very large result came back as a truncation envelope wrapped in a truncation
129
+ envelope whose `totalChars` reported the inner envelope's length rather than
130
+ the real size. Previews are somewhat shorter; `totalChars` is now the true
131
+ serialized size of what the program returned.
132
+
5
133
  ## 0.9.1 — 2026-07-29
6
134
 
7
135
  A code-mode routing release. Agents that needed an unknown address *and* a
package/README.md CHANGED
@@ -2,104 +2,61 @@
2
2
 
3
3
  ![A monochrome clay Connecta hub joining many tools](./assets/connecta-clay-hero.png)
4
4
 
5
- One MCP endpoint in front of every integration you've deliberately chosen.
6
- Agents see a handful of meta-tools instead of hundreds of definitions, and each
7
- client is configured once instead of once per integration.
8
-
9
- ## What connecta is
10
-
11
- An agent connected to N MCP servers pays for all N before it does anything:
12
- every server's full tool list lands in the context window at connect time, and
13
- every client is pointed at every server separately, each with its own auth.
14
- Connecta is one endpoint you deploy instead — a Cloudflare Worker or a Node
15
- process, same code either way — aggregating your connectors behind nine
16
- meta-tools. A connector is a remote MCP server connecta proxies or a plain
17
- HTTP API with hand-written tool definitions; both come out identical,
18
- addressed as `<connectorId>.<toolName>`.
19
-
20
- ```
21
- ┌── remoteMcp("notion") → mcp.notion.com
22
- Claude / Cursor ── MCP ──▶ connecta ───┼── remoteMcp("linear") → mcp.linear.app
23
- sees 9 tools /mcp ├── api("resend") → fetch(...)
24
- └── api("internal") → fetch(...)
25
- ```
26
-
27
- The agent discovers instead of preloading: `search_tools` ranks matches and can
28
- return their compact schemas in the same response, while `describe_tools`
29
- expands only schemas that remain unclear. `call_tool` / `batch_call` /
30
- `call_destructive_tool` invoke them, and `list_connectors`,
31
- `authorize_connector`, `get_result`, and `skills` round out the nine. An
32
- optional tenth, `execute_code`, runs model-written JavaScript in a sandbox with
33
- no network, filesystem, or environment access — only the read-only tools in
34
- scope. Context holds nine definitions whether ten tools sit behind them or a
35
- thousand.
36
-
37
- Three properties are load-bearing enough to name here; the rest live in the
38
- [ethos](./ethos.md). **Read-only is fail-closed**: anything not explicitly
39
- annotated read-only crosses `call_destructive_tool`, which is annotated so the
40
- MCP host can ask a human. **Credentials stay server-side**: an encrypted
41
- vault, rotated from an operator page, and no surface ever returns a secret.
42
- **Config is code**: adding a connector is an edit and a deploy you can review
43
- in a pull request.
44
-
45
- ## Getting started
46
-
47
- Node deployments require Node.js 20.9 or newer.
48
-
49
- ```sh
50
- npm install @zackbart/connecta
5
+ One place for AI agents to connect to the tools you choose.
6
+
7
+ Connecta gives an agent a single MCP endpoint instead of making it connect to
8
+ every service separately. You decide which integrations are available and
9
+ Connecta holds their credentials, and the agent mostly works by writing
10
+ ordinary JavaScript that Connecta runs in a sandbox next to them — with a few
11
+ explicit tools for the jobs a program is the wrong shape for, destructive calls
12
+ among them.
13
+
14
+ ```mermaid
15
+ flowchart LR
16
+ Agent["AI agent"]
17
+ Integrations["The integrations you chose"]
18
+
19
+ subgraph Connecta["Connecta: one MCP endpoint; credentials stay here"]
20
+ Sandbox["execute_code<br/>server-side sandbox"]
21
+ Explicit["Explicit tools<br/>destructive calls, search, auth"]
22
+ end
23
+
24
+ Agent -->|"writes a program"| Sandbox
25
+ Agent -->|"one deliberate call"| Explicit
26
+ Sandbox --> Integrations
27
+ Explicit --> Integrations
51
28
  ```
52
29
 
53
- A minimal server with one hand-written connector:
54
-
55
- ```ts
56
- import { api, bearerToken, createConnecta } from "@zackbart/connecta";
57
- import { fileStorage, listen } from "@zackbart/connecta/node";
30
+ ## Why Connecta
58
31
 
59
- const connecta = createConnecta({
60
- storage: fileStorage("./.connecta-state.json"), // or memoryStorage()
61
- auth: bearerToken(process.env.CONNECTA_TOKEN ?? "dev-token"),
62
- connectors: [
63
- api("time", {
64
- description: "Time current timestamp",
65
- tools: [
66
- {
67
- name: "get_now",
68
- description: "Return the current time as an ISO 8601 timestamp.",
69
- inputSchema: { type: "object", properties: {} },
70
- annotations: { readOnlyHint: true },
71
- handler: async () => ({ now: new Date().toISOString() }),
72
- },
73
- ],
74
- }),
75
- ],
76
- });
32
+ - **One connection.** Configure clients once, even as integrations change.
33
+ - **Seven tools, not seven hundred.** A program can search the catalog, chain
34
+ calls, and trim the results before the agent ever sees them — so nothing has
35
+ to be loaded up front.
36
+ - **Safer access.** Credentials stay server-side — the program never sees them
37
+ and consequential actions remain explicit and individual.
38
+ - **Named client access.** A Clerk operator can issue and revoke one-time,
39
+ hashed Bearer tokens for MCP clients that support header authentication.
40
+ - **Your deployment.** Connecta runs on Node, Docker, or Cloudflare Workers,
41
+ with configuration you can review and version.
77
42
 
78
- listen(connecta, 8787); // MCP at /mcp; Connections at http://localhost:8787/
79
- ```
43
+ ## Start here
80
44
 
81
- Point an MCP client at `http://localhost:8787/mcp` with an
82
- `Authorization: Bearer` header and `time.get_now` is discoverable through
83
- `search_tools`.
45
+ - [Node example](./examples/node/)
46
+ - [Docker example](./examples/docker/)
47
+ - [Cloudflare Worker example](./examples/worker/)
48
+ - [Documentation](./documentation/)
84
49
 
85
- Runnable deployments live in
86
- [`examples/`](https://github.com/zackbart/connecta/tree/main/examples): a
87
- free-tier-compatible Cloudflare Worker with KV and D1 adapters, a Node server
88
- extending the one above, and a single-service Docker compose stack.
89
- Heavyweight extras are optional peers behind subpaths (`/auth/clerk`,
90
- `/quickjs`), and connecta ships no service-specific connectors — endpoint,
91
- credential, and tool choices stay in your project.
50
+ Configuring a sandbox — a Dynamic Worker on Cloudflare, QuickJS on Node — is
51
+ what selects the code-first surface, and it is the assumed posture. A
52
+ deployment without one keeps the earlier nine-tool, call-by-call interface,
53
+ which stays supported.
92
54
 
93
- A candid note on maturity: connecta is built for its author's deployments
94
- first and published openly. Breaking changes are cheap and the version number
95
- signals change, not stability — the [ethos](./ethos.md) says so on purpose.
55
+ ## Project status
96
56
 
97
- ## Learn more
57
+ Connecta is built for its author's deployments first and is still evolving.
58
+ Breaking changes are expected before 1.0.
98
59
 
99
- - **[ethos.md](./ethos.md)** what this is, what it refuses to be, the
100
- decisions table, and the invariants. Read it before proposing anything.
101
- - **[documentation/](./documentation/)** — per-subsystem guides (currently
102
- stubs; the prior manual lives in git history).
103
- - **[CHANGELOG](./CHANGELOG.md)** — what changed in each release.
104
- - **[SECURITY](./SECURITY.md)** — supported versions and how to report a
105
- vulnerability.
60
+ Read the [ethos](./ethos.md) for the product's principles, the
61
+ [changelog](./CHANGELOG.md) for releases, and [security policy](./SECURITY.md)
62
+ for vulnerability reporting.
@@ -0,0 +1,32 @@
1
+ import type { InboundAuth, KVStorage } from "./types.js";
2
+ export interface AccessTokenMetadata {
3
+ id: string;
4
+ name: string;
5
+ tokenPrefix: string;
6
+ createdAt: string;
7
+ revokedAt?: string;
8
+ }
9
+ export interface CreatedAccessToken {
10
+ token: string;
11
+ accessToken: AccessTokenMetadata;
12
+ }
13
+ /**
14
+ * Deployment-scoped personal access tokens. Secret material is never
15
+ * recoverable: authentication indexes a SHA-256 digest of a random 256-bit
16
+ * token, while separately enumerable metadata powers operator management.
17
+ */
18
+ export declare class AccessTokenManager {
19
+ private readonly storage;
20
+ readonly auth: InboundAuth;
21
+ private readonly maxActive;
22
+ constructor(storage: KVStorage, options?: {
23
+ maxActive?: number;
24
+ });
25
+ private read;
26
+ list(): Promise<AccessTokenMetadata[]>;
27
+ create(name: unknown, createdBy: string): Promise<CreatedAccessToken>;
28
+ rename(id: string, name: unknown): Promise<AccessTokenMetadata | null>;
29
+ revoke(id: string, revokedBy: string): Promise<AccessTokenMetadata | null>;
30
+ private authorize;
31
+ }
32
+ //# sourceMappingURL=access-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-tokens.d.ts","sourceRoot":"","sources":["../src/access-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA6BrE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,mBAAmB,CAAC;CAClC;AAyGD;;;;GAIG;AACH,qBAAa,kBAAkB;IAK3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGhB,OAAO,EAAE,SAAS,EACnC,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO;YAgCxB,IAAI;IAKZ,IAAI,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IActC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAoCrE,MAAM,CACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAQhC,MAAM,CACV,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;YAexB,SAAS;CAgBxB"}
@@ -0,0 +1,225 @@
1
+ const TOKEN_PREFIX = "cta_";
2
+ const TOKEN_BYTES = 32;
3
+ const TOKEN_VALUE_RE = /^cta_[A-Za-z0-9_-]{43}$/;
4
+ const RECORD_PREFIX = "access-token:v1:record:";
5
+ const LOOKUP_PREFIX = "access-token:v1:lookup:";
6
+ const MAX_NAME_CHARACTERS = 80;
7
+ const DEFAULT_MAX_ACTIVE = 100;
8
+ const MAX_CONFIGURED_ACTIVE = 1_000;
9
+ const encoder = new TextEncoder();
10
+ function recordKey(id) {
11
+ return `${RECORD_PREFIX}${id}`;
12
+ }
13
+ function lookupKey(hash) {
14
+ return `${LOOKUP_PREFIX}${hash}`;
15
+ }
16
+ function bytesToBase64Url(bytes) {
17
+ let binary = "";
18
+ for (const byte of bytes)
19
+ binary += String.fromCharCode(byte);
20
+ return btoa(binary)
21
+ .replaceAll("+", "-")
22
+ .replaceAll("/", "_")
23
+ .replace(/=+$/u, "");
24
+ }
25
+ function bytesToHex(bytes) {
26
+ return [...bytes]
27
+ .map((byte) => byte.toString(16).padStart(2, "0"))
28
+ .join("");
29
+ }
30
+ async function hashToken(token) {
31
+ return bytesToHex(new Uint8Array(await crypto.subtle.digest("SHA-256", encoder.encode(token))));
32
+ }
33
+ function normalizeName(value) {
34
+ if (typeof value !== "string") {
35
+ throw new Error("Token name must be a string");
36
+ }
37
+ const compact = value.replace(/\s+/gu, " ").trim();
38
+ if (!compact)
39
+ throw new Error("Token name cannot be empty");
40
+ if (Array.from(compact).length > MAX_NAME_CHARACTERS) {
41
+ throw new Error(`Token name cannot exceed ${MAX_NAME_CHARACTERS} characters`);
42
+ }
43
+ return compact;
44
+ }
45
+ function parseRecord(raw) {
46
+ try {
47
+ const value = JSON.parse(raw);
48
+ if (value.version !== 1 ||
49
+ typeof value.id !== "string" ||
50
+ !/^[0-9a-f-]{36}$/u.test(value.id) ||
51
+ typeof value.name !== "string" ||
52
+ typeof value.tokenHash !== "string" ||
53
+ !/^[0-9a-f]{64}$/u.test(value.tokenHash) ||
54
+ typeof value.tokenPrefix !== "string" ||
55
+ typeof value.createdAt !== "string" ||
56
+ typeof value.createdBy !== "string" ||
57
+ (value.revokedAt !== undefined &&
58
+ typeof value.revokedAt !== "string") ||
59
+ (value.revokedBy !== undefined &&
60
+ typeof value.revokedBy !== "string")) {
61
+ throw new Error("invalid token record");
62
+ }
63
+ return value;
64
+ }
65
+ catch {
66
+ throw new Error("Stored access token metadata is invalid or corrupted");
67
+ }
68
+ }
69
+ function parseLookup(raw) {
70
+ try {
71
+ const value = JSON.parse(raw);
72
+ return value.version === 1 && typeof value.id === "string"
73
+ ? { version: 1, id: value.id }
74
+ : null;
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ function metadata(record) {
81
+ return {
82
+ id: record.id,
83
+ name: record.name,
84
+ tokenPrefix: record.tokenPrefix,
85
+ createdAt: record.createdAt,
86
+ ...(record.revokedAt ? { revokedAt: record.revokedAt } : {}),
87
+ };
88
+ }
89
+ function unauthorized() {
90
+ return {
91
+ ok: false,
92
+ response: new Response(JSON.stringify({ error: "unauthorized" }), {
93
+ status: 401,
94
+ headers: {
95
+ "Content-Type": "application/json",
96
+ "WWW-Authenticate": "Bearer",
97
+ },
98
+ }),
99
+ };
100
+ }
101
+ /**
102
+ * Deployment-scoped personal access tokens. Secret material is never
103
+ * recoverable: authentication indexes a SHA-256 digest of a random 256-bit
104
+ * token, while separately enumerable metadata powers operator management.
105
+ */
106
+ export class AccessTokenManager {
107
+ storage;
108
+ auth;
109
+ maxActive;
110
+ constructor(storage, options = {}) {
111
+ this.storage = storage;
112
+ if (!storage.list) {
113
+ throw new Error("accessTokens requires a storage adapter that implements list(prefix)");
114
+ }
115
+ const maxActive = options.maxActive ?? DEFAULT_MAX_ACTIVE;
116
+ if (!Number.isInteger(maxActive) ||
117
+ maxActive < 1 ||
118
+ maxActive > MAX_CONFIGURED_ACTIVE) {
119
+ throw new Error(`accessTokens.maxActive must be a whole number from 1 to ${MAX_CONFIGURED_ACTIVE}`);
120
+ }
121
+ this.maxActive = maxActive;
122
+ this.auth = {
123
+ kind: "access_token",
124
+ activityActorNamespace: "connecta:access-tokens:v1",
125
+ activityActorLabel: async (id) => {
126
+ try {
127
+ return (await this.read(id))?.name;
128
+ }
129
+ catch {
130
+ return undefined;
131
+ }
132
+ },
133
+ authorize: (request) => this.authorize(request),
134
+ };
135
+ }
136
+ async read(id) {
137
+ const raw = await this.storage.get(recordKey(id));
138
+ return raw ? parseRecord(raw) : null;
139
+ }
140
+ async list() {
141
+ const keys = await this.storage.list(RECORD_PREFIX);
142
+ const records = await Promise.all(keys.map(async (key) => {
143
+ const raw = await this.storage.get(key);
144
+ return raw ? parseRecord(raw) : null;
145
+ }));
146
+ return records
147
+ .filter((record) => Boolean(record))
148
+ .sort((a, b) => b.createdAt.localeCompare(a.createdAt))
149
+ .map(metadata);
150
+ }
151
+ async create(name, createdBy) {
152
+ const normalizedName = normalizeName(name);
153
+ const active = (await this.list()).filter((token) => !token.revokedAt);
154
+ if (active.length >= this.maxActive) {
155
+ throw new Error(`This deployment already has the maximum of ${this.maxActive} active access tokens`);
156
+ }
157
+ const secretBytes = crypto.getRandomValues(new Uint8Array(TOKEN_BYTES));
158
+ const token = TOKEN_PREFIX + bytesToBase64Url(secretBytes);
159
+ const hash = await hashToken(token);
160
+ if (await this.storage.get(lookupKey(hash))) {
161
+ throw new Error("Access token collision; create another token");
162
+ }
163
+ const record = {
164
+ version: 1,
165
+ id: crypto.randomUUID(),
166
+ name: normalizedName,
167
+ tokenHash: hash,
168
+ tokenPrefix: token.slice(0, 12),
169
+ createdAt: new Date().toISOString(),
170
+ createdBy,
171
+ };
172
+ await this.storage.set(recordKey(record.id), JSON.stringify(record));
173
+ try {
174
+ await this.storage.set(lookupKey(hash), JSON.stringify({ version: 1, id: record.id }));
175
+ }
176
+ catch (error) {
177
+ await this.storage.delete(recordKey(record.id)).catch(() => { });
178
+ throw error;
179
+ }
180
+ return { token, accessToken: metadata(record) };
181
+ }
182
+ async rename(id, name) {
183
+ const record = await this.read(id);
184
+ if (!record)
185
+ return null;
186
+ record.name = normalizeName(name);
187
+ await this.storage.set(recordKey(id), JSON.stringify(record));
188
+ return metadata(record);
189
+ }
190
+ async revoke(id, revokedBy) {
191
+ const record = await this.read(id);
192
+ if (!record)
193
+ return null;
194
+ if (!record.revokedAt) {
195
+ // Admission disappears first. A metadata-write failure may leave the UI
196
+ // calling the record active, but can never leave a token labelled
197
+ // revoked while its lookup still admits requests.
198
+ await this.storage.delete(lookupKey(record.tokenHash));
199
+ record.revokedAt = new Date().toISOString();
200
+ record.revokedBy = revokedBy;
201
+ await this.storage.set(recordKey(id), JSON.stringify(record));
202
+ }
203
+ return metadata(record);
204
+ }
205
+ async authorize(request) {
206
+ const header = request.headers.get("authorization") ?? "";
207
+ const match = /^Bearer\s+(.+)$/iu.exec(header);
208
+ const token = match?.[1];
209
+ if (!token || !TOKEN_VALUE_RE.test(token))
210
+ return unauthorized();
211
+ const hash = await hashToken(token);
212
+ const lookupRaw = await this.storage.get(lookupKey(hash));
213
+ if (!lookupRaw)
214
+ return unauthorized();
215
+ const lookup = parseLookup(lookupRaw);
216
+ if (!lookup)
217
+ return unauthorized();
218
+ const record = await this.read(lookup.id);
219
+ if (!record || record.revokedAt || record.tokenHash !== hash) {
220
+ return unauthorized();
221
+ }
222
+ return { ok: true, subjectId: record.id };
223
+ }
224
+ }
225
+ //# sourceMappingURL=access-tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-tokens.js","sourceRoot":"","sources":["../src/access-tokens.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-service.d.ts","sourceRoot":"","sources":["../src/catalog-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"catalog-service.d.ts","sourceRoot":"","sources":["../src/catalog-service.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { compactSchema, lexicalCorpusStatistics, lexicalSearchQuery, rankTools, schemaObjectKeys, summarizeDescription, } from "./catalog.js";
2
2
  import { mapSettledWithConcurrency, resolveDiscoveryConcurrency, } from "./concurrency.js";
3
- import { classifyCallError, messageLooksRetryable } from "./errors.js";
3
+ import { classifyCallError, framingError } from "./errors.js";
4
4
  import { connectorGuide, connectorSkillName, } from "./skills.js";
5
5
  import { DEFAULT_PROBE_TIMEOUT_MS, normalizeTimeoutMs, withAbortableTimeout, } from "./timeout.js";
6
6
  export const DEFAULT_SEARCH_LIMIT = 8;
@@ -68,9 +68,6 @@ function schemaKeyMetadata(input, output) {
68
68
  ...(outputKeys ? { outputKeys: outputKeys.properties } : {}),
69
69
  };
70
70
  }
71
- function framingError(code, message) {
72
- return { code, message, retryable: messageLooksRetryable(message) };
73
- }
74
71
  function renderSchema(schema, format) {
75
72
  return format === "json" ? schema : compactSchema(schema);
76
73
  }