@zackbart/connecta 0.37.0 → 0.38.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 +80 -0
- package/README.md +2 -2
- package/bin/connecta.mjs +1 -39
- package/bin/version.mjs +1 -1
- package/dist/access-tokens.js +2 -4
- package/dist/agent-identity.js +1 -1
- package/dist/auth/clerk-sdk/generated.js +2 -1
- package/dist/auth/cloudflare-access.d.ts +3 -1
- package/dist/auth/cloudflare-access.js +22 -11
- package/dist/auth/downstream-oauth.js +195 -270
- package/dist/auth/downstream-revocation.js +1 -1
- package/dist/auth/oauth-grant.js +11 -0
- package/dist/auth/oauth-token-response.js +1 -1
- package/dist/auth/vercel-agent.js +2 -1
- package/dist/auth-elicitation.js +2 -2
- package/dist/branding.d.ts +1 -15
- package/dist/branding.js +2 -2
- package/dist/bytes.js +42 -0
- package/dist/call-admission-context.js +2 -5
- package/dist/call-admission.js +5 -0
- package/dist/call-recovery.js +0 -3
- package/dist/catalog-cache.js +26 -7
- package/dist/catalog-fingerprint.js +2 -18
- package/dist/catalog-revision.js +9 -0
- package/dist/catalog-service.js +51 -20
- package/dist/config-defaults.d.ts +1 -0
- package/dist/config-defaults.js +1 -0
- package/dist/config-schema.d.ts +1 -1
- package/dist/config-schema.js +6 -2
- package/dist/config.d.ts +41 -14
- package/dist/config.js +21 -71
- package/dist/connector-caller.js +1 -1
- package/dist/connectors/api-connector.js +4 -3
- package/dist/connectors/guarded-fetch.d.ts +0 -6
- package/dist/connectors/guarded-fetch.js +1 -11
- package/dist/connectors/remote-mcp.js +93 -69
- package/dist/connectors/resource-uri.js +0 -4
- package/dist/credentials.js +3 -0
- package/dist/d1.d.ts +0 -89
- package/dist/d1.js +0 -34
- package/dist/downstream-input.js +2 -2
- package/dist/execute.js +161 -116
- package/dist/executor-result.js +2 -1
- package/dist/executors/quickjs-runtime.js +2 -25
- package/dist/executors/quickjs.js +1 -1
- package/dist/guest-runtime.js +5 -3
- package/dist/guest-types.d.ts +5 -5
- package/dist/http/client.js +1 -1
- package/dist/http/errors.js +2 -2
- package/dist/http/json-schema.js +1 -1
- package/dist/http/node-transport.js +0 -1
- package/dist/http/oauth.js +1 -1
- package/dist/http/paging.js +6 -9
- package/dist/http/provider.js +1 -1
- package/dist/http/safety.js +1 -1
- package/dist/http/services.js +1 -8
- package/dist/http/tools.js +1 -7
- package/dist/http/vendor.js +7 -7
- package/dist/identity.js +2 -6
- package/dist/index.js +1 -2
- package/dist/invocation-auth.js +2 -1
- package/dist/invocation.js +8 -2
- package/dist/meta-tools.js +27 -27
- package/dist/native-tools.js +2 -1
- package/dist/oauth-handoff.js +2 -2
- package/dist/operation-vocabulary.js +1 -1
- package/dist/operator-record.d.ts +8 -2
- package/dist/operator-record.js +18 -50
- package/dist/operator-ui/contract.d.ts +4 -2
- package/dist/operator-ui/generated.js +3 -3
- package/dist/operator-ui/model.d.ts +7 -2
- package/dist/program-writes.js +3 -8
- package/dist/provider-call.js +0 -7
- package/dist/provider.d.ts +1 -1
- package/dist/providers/_shared/google/kit.js +1 -6
- package/dist/providers/_shared/google/service-account.js +1 -3
- package/dist/providers/_shared/google/workspace.d.ts +1 -1
- package/dist/providers/_shared/guide.js +3 -0
- package/dist/providers/_shared/json.js +12 -0
- package/dist/providers/_shared/rest/compact-index.js +1 -1
- package/dist/providers/_shared/rest/kit.js +1 -3
- package/dist/providers/_shared/rest/operation-index.js +1 -3
- package/dist/providers/_shared/rest/value-safety.js +26 -28
- package/dist/providers/breeze/api.js +2 -7
- package/dist/providers/breeze/index.js +4 -2
- package/dist/providers/breeze/tools.js +3 -4
- package/dist/providers/ccb/api.js +1 -6
- package/dist/providers/ccb/index.js +2 -1
- package/dist/providers/ccb/tools.js +1 -6
- package/dist/providers/cloudflare/api.js +2 -2
- package/dist/providers/cloudflare/index.js +2 -1
- package/dist/providers/cloudflare/safety.js +3 -3
- package/dist/providers/docs/tools.js +2 -10
- package/dist/providers/drive/tools.js +12 -25
- package/dist/providers/forms/tools.js +1 -9
- package/dist/providers/gmail/tools.js +5 -21
- package/dist/providers/overflow/api.js +1 -3
- package/dist/providers/overflow/index.js +2 -1
- package/dist/providers/overflow/tools.js +3 -7
- package/dist/providers/planning-center/api.js +2 -1
- package/dist/providers/planning-center/lib/constants.d.ts +1 -1
- package/dist/providers/planning-center/lib/json-api.js +1 -9
- package/dist/providers/planning-center/tools.js +2 -1
- package/dist/providers/sheets/tools.js +1 -9
- package/dist/providers/slides/tools.js +4 -13
- package/dist/providers/stripe/index.js +2 -1
- package/dist/providers/stripe/safety.js +2 -2
- package/dist/providers/tithely/api.js +2 -7
- package/dist/providers/tithely/index.js +3 -2
- package/dist/providers/tithely/tools.js +7 -5
- package/dist/providers/vercel/api.js +1 -6
- package/dist/providers/vercel/lib/pin.js +1 -1
- package/dist/providers/vercel/safety.js +1 -1
- package/dist/providers/vercel/tools.js +2 -1
- package/dist/redaction-marker.js +2 -2
- package/dist/registry.d.ts +4 -1
- package/dist/registry.js +35 -22
- package/dist/request-principal.js +15 -2
- package/dist/request-state.js +2 -2
- package/dist/routes/access-tokens.js +1 -1
- package/dist/routes/activity-disclosure.js +1 -1
- package/dist/routes/connect.js +2 -2
- package/dist/routes/credentials.js +1 -1
- package/dist/routes/dispatch.js +10 -0
- package/dist/routes/mcp.js +23 -21
- package/dist/routes/oauth-management.js +1 -1
- package/dist/routes/operator.js +53 -7
- package/dist/routes/shared.d.ts +8 -8
- package/dist/routes/shared.js +22 -15
- package/dist/routes/ui-config.js +6 -6
- package/dist/routes/ui-data.js +2 -2
- package/dist/routes/ui.js +9 -4
- package/dist/runtime/call-admission.js +1 -1
- package/dist/runtime/call.js +1 -1
- package/dist/runtime/settlement.js +1 -1
- package/dist/runtime/shared-read.js +2 -15
- package/dist/sent-secrets.d.ts +14 -6
- package/dist/sent-secrets.js +231 -85
- package/dist/server.js +4 -4
- package/dist/skills.js +8 -35
- package/dist/sqlite.d.ts +0 -19
- package/dist/sqlite.js +2 -83
- package/dist/storage/keys.js +29 -124
- package/dist/storage/sql-native.js +14 -111
- package/dist/storage/sql.d.ts +1 -24
- package/dist/storage/sql.js +1 -12
- package/dist/tool-error.js +4 -0
- package/dist/types.d.ts +4 -3
- package/dist/ui.js +3 -0
- package/dist/url-safety.js +0 -4
- package/dist/usage-guide.js +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.js +1 -1
- package/documentation/README.md +6 -42
- package/documentation/architecture.md +190 -507
- package/documentation/auth.md +172 -58
- package/documentation/code-mode.md +98 -66
- package/documentation/deploying.md +19 -40
- package/documentation/integrating.md +8 -19
- package/documentation/meta-tools.md +23 -6
- package/documentation/migration-0.33.md +5 -5
- package/documentation/migration-0.34.md +2 -4
- package/documentation/migration-retired-layouts.md +74 -0
- package/documentation/operator-tests.md +19 -119
- package/documentation/operator-ui.md +46 -8
- package/documentation/provider-auth-migration.md +4 -10
- package/documentation/provider-migration-0.29.md +4 -15
- package/examples/worker/AGENTS.md +4 -6
- package/examples/worker/README.md +20 -115
- package/guides/connecting-agents.md +7 -30
- package/guides/how-it-works.md +2 -2
- package/guides/safety-and-trust.md +4 -1
- package/package.json +19 -19
- package/templates/node/README.md +9 -26
- package/templates/node/package.json +1 -1
- package/dist/auth/oauth-v2-migration.js +0 -135
- package/dist/provider-call-facts.d.ts +0 -115
- package/dist/provider-call.d.ts +0 -112
- package/dist/storage/d1-copy.js +0 -255
- package/dist/storage/sql-schema.d.ts +0 -6
- package/examples/worker/kv-to-d1.wrangler.jsonc +0 -26
- package/examples/worker/scripts/copy-kv-to-d1.mjs +0 -162
package/documentation/auth.md
CHANGED
|
@@ -1286,16 +1286,13 @@ connector](#downstream-oauth-on-api) stores no client. A vault without the
|
|
|
1286
1286
|
optional `seal`/`open` members keeps the body plaintext with a startup
|
|
1287
1287
|
warning; no vault, plaintext as always.
|
|
1288
1288
|
|
|
1289
|
-
**
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
from before issuer binding (v0.8.1 and earlier) and pending consents are not
|
|
1297
|
-
carried, so those connectors need Connect again. Rolling back past this
|
|
1298
|
-
release finds no layout-2 grant and needs consent.
|
|
1289
|
+
**Pre-layout-3 grants.** The layout-2 migration and historical-key cleanup
|
|
1290
|
+
are removed. An owner with only old keys is treated as unauthorized; a warning
|
|
1291
|
+
names the unsupported layout and the need to Connect again or migrate on
|
|
1292
|
+
0.37.1. The check inspects key names only, never old credential values, and
|
|
1293
|
+
leaves them untouched. Existing layout-3 records remain readable even with an
|
|
1294
|
+
obsolete cleanup marker. Complete every owner's grant migration on 0.37.1
|
|
1295
|
+
before upgrading, or reconnect afterward; follow [Retired layout migrations](./migration-retired-layouts.md).
|
|
1299
1296
|
|
|
1300
1297
|
## Starting, restarting, and disconnecting
|
|
1301
1298
|
|
|
@@ -1349,12 +1346,15 @@ with the gate a call passes:
|
|
|
1349
1346
|
| Tokens (any expiry) | Connects; `ok`, or `auth_required` when a 401 needs consent | Connects; `ok` without starting a flow when healthy |
|
|
1350
1347
|
|
|
1351
1348
|
A start without a challenge runs the same SDK flow as a 401 without
|
|
1352
|
-
`resource_metadata`.
|
|
1349
|
+
`resource_metadata`. An explicit start after a status check or call in the same
|
|
1350
|
+
request scope can start consent in the connection's original epoch; the status
|
|
1351
|
+
check and call remain passive. Issuer and resource checks, consent state, PKCE, and
|
|
1353
1352
|
the CIMD, registration, and static-client order are unchanged, and nothing is
|
|
1354
1353
|
sent to the MCP endpoint. A call never starts consent. A call's 401 that names
|
|
1355
1354
|
per-tool metadata, such as `/.well-known/oauth-protected-resource/<tool>`,
|
|
1356
|
-
renews through it when the grant holds no discovery.
|
|
1357
|
-
|
|
1355
|
+
renews through it when the grant holds no discovery. The challenged metadata
|
|
1356
|
+
URL must share the configured connector URL's origin, and its metadata must
|
|
1357
|
+
name the configured resource, as any other must. When renewal is refused, the grant
|
|
1358
1358
|
loses its tokens and the next start hands out consent. Restart (`force: true`)
|
|
1359
1359
|
removes the tokens first, so it starts consent unless the downstream or
|
|
1360
1360
|
discovery fails.
|
|
@@ -1394,12 +1394,8 @@ exchange. Both built-in `finishAuth` adapters require `callbackParams` with a
|
|
|
1394
1394
|
nonempty `state`, even with PKCE disabled or after a separate `verifyState` call.
|
|
1395
1395
|
A missing state is refused before discovery, registration, or token dispatch.
|
|
1396
1396
|
|
|
1397
|
-
|
|
1398
|
-
historical keys.
|
|
1399
|
-
marker by CAS only when deletion succeeds. Restart preserves this obligation.
|
|
1400
|
-
Disconnect commits a tombstone with the marker and always removes historical
|
|
1401
|
-
keys for the connector and owner, including when a modern grant already exists.
|
|
1402
|
-
A crash during cleanup cannot restore the disconnected grant.
|
|
1397
|
+
Disconnect commits a layout-3 tombstone. Restart and Disconnect never read or
|
|
1398
|
+
restore historical layout-2 keys.
|
|
1403
1399
|
|
|
1404
1400
|
Disconnect first removes the grant and fences its epoch with CAS. When that
|
|
1405
1401
|
removed grant's saved authorization-server metadata advertises a revocation
|
|
@@ -1431,7 +1427,7 @@ lease's `claimed` to `dispatched` CAS and a separate fingerprint CAS at
|
|
|
1431
1427
|
`oauth:refresh-spent:<sha256(refresh_token)>`. The latter must succeed before
|
|
1432
1428
|
any HTTP request leaves. Connector and owner storage namespaces partition both
|
|
1433
1429
|
records. Spent records have **no TTL**, contain no token, and are never deleted
|
|
1434
|
-
by completion, failure,
|
|
1430
|
+
by completion, failure, Restart, Disconnect, or epoch sweeps.
|
|
1435
1431
|
Copy these durable records during storage migration.
|
|
1436
1432
|
|
|
1437
1433
|
Each fingerprint record names its dispatch epoch, holder, and resolution state:
|
|
@@ -1475,13 +1471,13 @@ body contains tokens. Fetch has already sent the request body; a refresh
|
|
|
1475
1471
|
fingerprint is resolved as a definitive failure and the grant requires re-consent. A
|
|
1476
1472
|
redirected code exchange is refused and its SDK retry cannot resend the code.
|
|
1477
1473
|
|
|
1478
|
-
| Outcome after dispatch | Result
|
|
1479
|
-
| ------------------------------------------------------------------------------------------------ |
|
|
1480
|
-
| Valid tokens durably committed | Mark the fingerprint resolved and release waiters with committed tokens. Within the epoch only a new fingerprint can be dispatched next.
|
|
1481
|
-
| Definitive provider failure | `auth_required`. Mark the fingerprint resolved and conditionally remove its grant tokens. Includes every 3xx without following it and complete failures such as 5xx, 408, 425, and 429.
|
|
1482
|
-
| Network or response-body loss, malformed or oversized success, deadline expiry, or process crash | `auth_required`. Mark the fingerprint ambiguous and conditionally remove its grant tokens. Identical-token re-consent cannot reopen it.
|
|
1483
|
-
| Valid rotation whose grant commit retries are exhausted | `auth_required`. Record the definitive commit failure as resolved and conditionally remove its grant tokens. Never return uncommitted tokens to the SDK.
|
|
1484
|
-
| Epoch changed during commit | Drop the response tokens and record the definitive failure as resolved. Restart, Disconnect, or issuer replacement determines the newer grant. A consent that completed before this resolution cannot reuse its fingerprint.
|
|
1474
|
+
| Outcome after dispatch | Result |
|
|
1475
|
+
| ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1476
|
+
| Valid tokens durably committed | Mark the fingerprint resolved and release waiters with committed tokens. Within the epoch only a new fingerprint can be dispatched next. |
|
|
1477
|
+
| Definitive provider failure | `auth_required`. Mark the fingerprint resolved and conditionally remove its grant tokens. Includes every 3xx without following it and complete failures such as 5xx, 408, 425, and 429. |
|
|
1478
|
+
| Network or response-body loss, malformed or oversized success, deadline expiry, or process crash | `auth_required`. Mark the fingerprint ambiguous and conditionally remove its grant tokens when storage answers within the cleanup bound. An outstanding fingerprint remains fenced if storage stalls. Identical-token re-consent cannot reopen it. |
|
|
1479
|
+
| Valid rotation whose grant commit retries are exhausted | `auth_required`. Record the definitive commit failure as resolved and conditionally remove its grant tokens. Never return uncommitted tokens to the SDK. |
|
|
1480
|
+
| Epoch changed during commit | Drop the response tokens and record the definitive failure as resolved. Restart, Disconnect, or issuer replacement determines the newer grant. A consent that completed before this resolution cannot reuse its fingerprint. |
|
|
1485
1481
|
|
|
1486
1482
|
Refreshes coalesce per owner and epoch within a runtime. Across isolates, a
|
|
1487
1483
|
shared-storage record at `oauth:refresh:<epoch>:<sha256(refresh_token)>` is
|
|
@@ -1494,7 +1490,10 @@ storage-owned 120-second TTL. SQLite and D1 create and check expiry with the
|
|
|
1494
1490
|
database clock inside each statement. Custom shared stores must also use a
|
|
1495
1491
|
storage-owned clock. Cross-isolate clock comparisons never permit takeover of
|
|
1496
1492
|
a dispatched record. The refresh HTTP request and response body have a
|
|
1497
|
-
20-second deadline.
|
|
1493
|
+
20-second deadline. After the response or a dispatched exchange failure,
|
|
1494
|
+
grant commit and cleanup share a separate 20-second deadline, including all
|
|
1495
|
+
storage reads, CAS retries, fingerprint resolution, and lease release.
|
|
1496
|
+
Contenders wait at most 35 seconds with 10 ms to 250 ms
|
|
1498
1497
|
backoff. A waiter deadline returns retryable `unavailable`, keeps the grant,
|
|
1499
1498
|
and starts no consent. It never permits resending a spent token.
|
|
1500
1499
|
|
|
@@ -1538,7 +1537,7 @@ preparation recorded the fingerprint as spent, it stays spent even if the send
|
|
|
1538
1537
|
was subsequently cancelled or a local destination guard refused it.
|
|
1539
1538
|
|
|
1540
1539
|
After dispatch, caller and SDK cancellation end only that caller's wait. The
|
|
1541
|
-
exchange and grant commit continue under
|
|
1540
|
+
exchange and grant commit continue under their own deadlines. The runtime passes
|
|
1542
1541
|
completion to Workers `waitUntil`; paths without that hook keep a background
|
|
1543
1542
|
promise. The holder re-reads the grant and retries the commit with its in-memory
|
|
1544
1543
|
response tokens up to 32 times after CAS contention or storage errors. Each
|
|
@@ -1547,6 +1546,16 @@ drops the response tokens. Another consent's credentials remain intact. A lost
|
|
|
1547
1546
|
commit answer can be recovered by reading the committed grant. Exhausting the
|
|
1548
1547
|
commit retries requires re-consent.
|
|
1549
1548
|
|
|
1549
|
+
Expiry of the commit/cleanup deadline reports `OAuth refresh outcome is unknown`
|
|
1550
|
+
and requires authorization. Every exit settles the local flight and releases its
|
|
1551
|
+
owner partition without awaiting further storage. Late storage answers cannot
|
|
1552
|
+
resume the expired coordinator or start another commit or completion write.
|
|
1553
|
+
An already submitted CAS may still land; unconfirmed grant commits leave the
|
|
1554
|
+
durable spent fingerprint outstanding, so the consumed token cannot be sent
|
|
1555
|
+
again. Later callers read durable state rather than joining an expired local
|
|
1556
|
+
flight. If cleanup could not finish, the storage-owned holder TTL allows them
|
|
1557
|
+
to record an ambiguous outcome and conditionally discard the old grant.
|
|
1558
|
+
|
|
1550
1559
|
Lease release uses CAS after the commit or re-consent decision. Completion
|
|
1551
1560
|
records include a SHA-256 digest of the committed token response, excluding
|
|
1552
1561
|
the local issuer stamp. Waiters can adopt that committed response even when
|
|
@@ -1649,13 +1658,37 @@ program returns, logs, and emits, and relayed input prompts. Each redaction
|
|
|
1649
1658
|
projects the whole value: string and number leaves in serialization order,
|
|
1650
1659
|
JSON objects, arrays, and string literals parsed into their own leaves whether
|
|
1651
1660
|
they are wire text or a string inside a result, and errors' own fields. The
|
|
1652
|
-
joined projection is matched
|
|
1661
|
+
joined projection is matched, so a value split across adjacent leaves,
|
|
1653
1662
|
such as text blocks or array items, is found; each match is replaced only in
|
|
1654
1663
|
the leaves it touches, and the containers around them keep their shape. A
|
|
1655
|
-
number
|
|
1656
|
-
|
|
1657
|
-
|
|
1664
|
+
number touched by a match is first checked again beside the replaced string
|
|
1665
|
+
pieces, with adjacent numbers checked together: a number stays numeric when
|
|
1666
|
+
string replacement breaks the match. Every replacement is then checked in the
|
|
1667
|
+
lane as it will be returned, including partial string replacements and whole
|
|
1668
|
+
numbers, typed binary, decoded binary, whole-field private values and unchecked
|
|
1669
|
+
runs. Omitted error numbers contribute empty text; a changed error name
|
|
1670
|
+
contributes one whole placeholder, including when its JSON text had several
|
|
1671
|
+
leaves. Whole JSON withholding and scalars withheld during the walk contribute
|
|
1672
|
+
their placeholders before settling. A new match touching a kept piece withholds
|
|
1673
|
+
that whole part. The lane is checked again until nothing changes, including
|
|
1674
|
+
runs formed from `[redacted]`
|
|
1675
|
+
and a kept string piece or number, within a string or across leaves. A span
|
|
1676
|
+
wholly inside a placeholder remains the placeholder.
|
|
1677
|
+
Each changing round withholds at least one more part, so there are at most as
|
|
1678
|
+
many changing rounds as parts. Every round, including its bookkeeping, shares
|
|
1679
|
+
the call's work budget; an unaffordable leaf or seam check withholds every
|
|
1680
|
+
participant, including previously untouched neighbours and every originally
|
|
1681
|
+
touched number still awaiting retention. A marker that could not itself be
|
|
1682
|
+
scanned remains in its seam windows. Unchanged lanes pay for no recheck.
|
|
1683
|
+
Joined and leaf-by-leaf checks follow the same rule; large lanes check
|
|
1684
|
+
changed parts and the seams touching them without rereading unchanged leaf
|
|
1685
|
+
interiors. Bounded lanes and deep escapes withhold changed numbers whole.
|
|
1686
|
+
Text is reserialized only when something changed; otherwise its original bytes
|
|
1687
|
+
remain. Serialized JSON whose keys, syntax, and leaves together hold a run
|
|
1658
1688
|
that no single leaf holds, as a value spanning tokens does, is withheld whole.
|
|
1689
|
+
Settling covers the joined leaves and whole replacement markers; object keys,
|
|
1690
|
+
JSON punctuation and fixed framing do not join that lane. Keys are checked
|
|
1691
|
+
alone, and serialized token-spanning matches use the whole-JSON rule above.
|
|
1659
1692
|
Matching runs on the raw text and through one more layer of JSON string escapes
|
|
1660
1693
|
at a time while the last layer still decodes an escape, at most eight layers;
|
|
1661
1694
|
text still holding escapes past that is withheld. Each decoded layer is scanned
|
|
@@ -1682,7 +1715,8 @@ fields that are refused instead of rewritten. Object keys are checked on their
|
|
|
1682
1715
|
own, and a key holding a match is renamed. Image, audio, resource-blob, or
|
|
1683
1716
|
`format: "base64"` content, or a REST body's `base64` beside its `contentType`,
|
|
1684
1717
|
is checked as text and also decoded whole and checked as bytes and as UTF-8,
|
|
1685
|
-
then withheld whole as the base64 of `[redacted]` on a match
|
|
1718
|
+
then withheld whole as the base64 of `[redacted]` on a match, or empty if
|
|
1719
|
+
that replacement encoding cannot be returned safely; content that is
|
|
1686
1720
|
not valid base64 as it stands is still checked through every text view. Base64
|
|
1687
1721
|
or base64url in any string is decoded and checked in each of the string's text
|
|
1688
1722
|
views: the text itself, the text with one layer of JSON escapes decoded
|
|
@@ -1771,10 +1805,15 @@ Every other value becomes the data JSON shows for it, checked, or is withheld:
|
|
|
1771
1805
|
|
|
1772
1806
|
Typed binary is withheld as `[redacted]` when its bytes hold a match, checked as
|
|
1773
1807
|
decoded binary content is, or when one of the numbers JSON shows for it does:
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1808
|
+
the returned `Uint8Array`'s byte numbers join neighbouring leaves directly.
|
|
1809
|
+
For non-byte typed arrays, a separate projection substitutes the original
|
|
1810
|
+
element numbers for the byte numbers, keeping the same neighbours. Neither
|
|
1811
|
+
numeric view interrupts the other; the raw byte view is checked on its own.
|
|
1812
|
+
A match in either numeric projection withholds the binary as one whole part,
|
|
1813
|
+
so its placeholder is checked beside its neighbours before return. Each number
|
|
1814
|
+
is also checked as a whole field: a one-to-three-character numeric private
|
|
1815
|
+
value, such as `7`, withholds a typed array holding that element, as it
|
|
1816
|
+
withholds an equal JSON number. Each of those numbers is an entry
|
|
1778
1817
|
of the walk's 1,048,576-entry budget, so binary past it is withheld whole.
|
|
1779
1818
|
Connecta returns downstream binary as base64 text, which none of this limits;
|
|
1780
1819
|
only in-process code can return a typed array. With nothing registered for a
|
|
@@ -1857,7 +1896,33 @@ structured value, and before result paging, emits, and program outputs/errors/lo
|
|
|
1857
1896
|
|
|
1858
1897
|
`remoteMcp()` learns server-side fetch URLs from a 401's `resource_metadata`,
|
|
1859
1898
|
its `authorization_servers`, and advertised token and registration endpoints.
|
|
1860
|
-
|
|
1899
|
+
A challenged `resource_metadata` URL must have the same origin as the
|
|
1900
|
+
configured connector `url`: scheme, host, and port after normal URL parsing.
|
|
1901
|
+
This applies during status, authorization starts, and tool calls. A different
|
|
1902
|
+
origin is refused before SDK discovery, with non-retryable
|
|
1903
|
+
`connector_call_failed` and a fixed message that includes no challenged URL
|
|
1904
|
+
or host; there is no allowlist.
|
|
1905
|
+
|
|
1906
|
+
Before every SDK discovery read, including authorization callbacks and flows
|
|
1907
|
+
without a challenge, a cached `resourceMetadataUrl` outside the configured
|
|
1908
|
+
origin (or a malformed URL) and its cached resource document are discarded
|
|
1909
|
+
from the discovery state given to the SDK. The stored grant is not changed by
|
|
1910
|
+
that read. The SDK rediscovers resource metadata using the current same-origin
|
|
1911
|
+
challenge, or the configured resource's same-origin well-known locations when
|
|
1912
|
+
there is no challenge. The cached authorization-server binding is retained so
|
|
1913
|
+
callback issuer checks still apply. If rediscovery changes a pending consent's
|
|
1914
|
+
discovery binding, its callback refuses before code exchange; start a new
|
|
1915
|
+
consent. If same-origin resource metadata returns 404, the cached
|
|
1916
|
+
authorization-server fallback can still complete consent against its stored
|
|
1917
|
+
binding. A foreign cached metadata URL is never requested, including when an older SDK flow saved only the URL after a 404.
|
|
1918
|
+
|
|
1919
|
+
Paths may differ: a resource at `https://crm.example.com/mcp` may challenge with
|
|
1920
|
+
`https://crm.example.com/oauth/resources/tickets`. Google's per-tool shape,
|
|
1921
|
+
`https://bigquery.googleapis.com/.well-known/oauth-protected-resource/<tool>`,
|
|
1922
|
+
is likewise accepted for a resource on `https://bigquery.googleapis.com`.
|
|
1923
|
+
|
|
1924
|
+
Other advertised OAuth URLs follow these rules to prevent a downstream from
|
|
1925
|
+
targeting the host's private network:
|
|
1861
1926
|
|
|
1862
1927
|
- A URL on the connector's configured origin is trusted; the operator wrote it.
|
|
1863
1928
|
- Any other URL must be `https` and must not name a private host: `localhost`
|
|
@@ -1869,8 +1934,9 @@ To prevent a downstream from targeting the host's private network:
|
|
|
1869
1934
|
working. LAN and link-local addresses stay refused.
|
|
1870
1935
|
|
|
1871
1936
|
A refused URL is never requested. Discovery, registration, and code exchange
|
|
1872
|
-
fail with a non-retryable `connector_call_failed
|
|
1873
|
-
|
|
1937
|
+
fail with a non-retryable `connector_call_failed`. Resource-metadata origin
|
|
1938
|
+
refusals include no advertised host; other URL refusals name only the host. A
|
|
1939
|
+
refused refresh never reaches the token endpoint. If the
|
|
1874
1940
|
send gate already recorded its fingerprint, that fingerprint remains blocked
|
|
1875
1941
|
and the grant requires re-consent. Redirects cannot route around the
|
|
1876
1942
|
rule; token requests never follow them, and resource redirects follow only
|
|
@@ -1908,8 +1974,8 @@ anything, so SDK hook order cannot mix servers or cross a reset.
|
|
|
1908
1974
|
|
|
1909
1975
|
Management follows `maintainers` and pool `members`; no resolver configures it. The former `identity.credentialAdministration`,
|
|
1910
1976
|
`identity.personalConnection`, `identity.accessTokenManagement`, and
|
|
1911
|
-
`identity.activityAccess`
|
|
1912
|
-
|
|
1977
|
+
`identity.activityAccess` fail construction as unknown options under `identity`,
|
|
1978
|
+
including an empty `identity` section.
|
|
1913
1979
|
|
|
1914
1980
|
| Action | Who may |
|
|
1915
1981
|
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -1998,16 +2064,35 @@ identity, or unusable user ids refuse. Access service credentials can admit the
|
|
|
1998
2064
|
request at the edge, but connecta requires a `cta_` token at `/agent/<pool>`
|
|
1999
2065
|
for machine identity.
|
|
2000
2066
|
|
|
2001
|
-
It never
|
|
2002
|
-
caller's JWT.
|
|
2003
|
-
|
|
2067
|
+
It never parses or verifies `Cf-Access-Jwt-Assertion`, fetches signing keys, or
|
|
2068
|
+
accepts a caller's JWT. The assertion header's presence is only an untrusted
|
|
2069
|
+
hint that Access context was expected: without `ctx.access`, that request
|
|
2070
|
+
returns retryable 503 with `problem: "access_context_unavailable"`, including
|
|
2071
|
+
the first request on a fresh instance. It grants no identity and never falls
|
|
2072
|
+
back to another provider. Missing context without an assertion still returns 401. An unusable trusted AUD returns retryable 503 with
|
|
2073
|
+
`problem: "access_audience_invalid"`; it never proceeds to identity lookup.
|
|
2074
|
+
A rejected human identity, including a service identity or an unusable user
|
|
2075
|
+
id, returns 403. A thrown identity lookup or its five-second deadline returns retryable
|
|
2004
2076
|
503 with `problem: "identity_unavailable"` and `Retry-After: 1`. Every refusal
|
|
2005
|
-
carries `Cache-Control: no-store
|
|
2077
|
+
carries `Cache-Control: no-store`; every unavailable-verification 503 carries
|
|
2078
|
+
`Retry-After: 1` and no `WWW-Authenticate` challenge. None of these failures admits an identity,
|
|
2006
2079
|
and an unavailable lookup never falls back to another provider. The operator
|
|
2007
2080
|
UI can re-request admission after a failure without a browser reload. It does not support Node, a `cloudflared` origin, or a Service Binding
|
|
2008
2081
|
hop.
|
|
2009
2082
|
Connecta configuration still decides connector access and management: `maintainers` and pool `members`.
|
|
2010
2083
|
|
|
2084
|
+
Every operator-surface 401 emits `[connecta] operator_refused` through the
|
|
2085
|
+
deployment logger. Its checked record contains `accessContext` (a boolean),
|
|
2086
|
+
`authorizationHeader` (`absent`, `bearer`, or `invalid`), and a closed `reason`
|
|
2087
|
+
code. Access codes distinguish `access_context_missing` from
|
|
2088
|
+
`access_authorization_header_rejected`; `authentication_provider_missing`
|
|
2089
|
+
identifies the generic route fallthrough, `authorization_header_invalid` a
|
|
2090
|
+
malformed header, and `authentication_failed` an unclassified provider refusal.
|
|
2091
|
+
Access verification 503s emit `[connecta] Cloudflare Access verification unavailable`
|
|
2092
|
+
with the same facts and `access_context_unavailable`, `access_audience_invalid`,
|
|
2093
|
+
or `access_identity_unavailable`. These records contain no header values,
|
|
2094
|
+
assertions, cookies, identities, URLs, response bodies, or exception text.
|
|
2095
|
+
|
|
2011
2096
|
Protect the Worker with a Worker-level Access application whose destination is
|
|
2012
2097
|
`{ "type": "worker", "worker_id": "<the Worker script tag>" }`. A traditional
|
|
2013
2098
|
hostname-level application blocks the URL but does not attach `ctx.access` to
|
|
@@ -2438,6 +2523,15 @@ need `consumeAuthError` to accept error callbacks, sharing `finishAuth`'s atomic
|
|
|
2438
2523
|
consent claim. Reissue
|
|
2439
2524
|
pending consent links after upgrading; callbacks without a saved initiating user cannot complete.
|
|
2440
2525
|
|
|
2526
|
+
A connector declares code-exchange support by implementing `finishAuth`. Omit
|
|
2527
|
+
that hook when the connector cannot exchange a code; `remoteMcp()` exposes it
|
|
2528
|
+
only for `auth: { type: "oauth" }`. A code-exchange connector without
|
|
2529
|
+
`verifyState` logs a construction warning naming the missing hook, and its
|
|
2530
|
+
browser callback refuses every request before exchanging a code. Implement
|
|
2531
|
+
`verifyState` to enable completion; credential, request-token (including Google
|
|
2532
|
+
service-account tokens), principal-forwarding, and header auth need no callback
|
|
2533
|
+
or state hook.
|
|
2534
|
+
|
|
2441
2535
|
Custom connectors may implement `verifyCallbackParameters(params, ctx)` for
|
|
2442
2536
|
provider-specific callback assertions. The route calls it after successful
|
|
2443
2537
|
state verification and before issuer validation, handoff consumption, error
|
|
@@ -2678,6 +2772,15 @@ transport, are not stored or described, and a changed token replaces the client.
|
|
|
2678
2772
|
This mode refuses cleartext non-loopback origins. Optional `auth.headers` carry
|
|
2679
2773
|
static protocol/catalog controls and cannot set Authorization.
|
|
2680
2774
|
|
|
2775
|
+
Status reports `auth_required` when a request-token or principal resolver returns
|
|
2776
|
+
an empty or invalid token or throws a typed authentication failure, including
|
|
2777
|
+
authentication failures from `googleServiceAccountToken`. Resolution failure
|
|
2778
|
+
sends no request to the MCP endpoint. Status uses the existing fixed authorization
|
|
2779
|
+
notice and never includes the resolver's error message. Typed outage and
|
|
2780
|
+
permission failures, and a resolver that throws anything other than a typed
|
|
2781
|
+
`ConnectorCallError`, remain error statuses; such an untyped failure still fails
|
|
2782
|
+
calls with `auth_required`.
|
|
2783
|
+
|
|
2681
2784
|
Return the same token for the same caller while it remains valid, and cache a
|
|
2682
2785
|
minted token until shortly before it expires. A value that changes on every
|
|
2683
2786
|
resolution replaces the client each time; a change that lands while a call
|
|
@@ -2736,11 +2839,26 @@ auth: {
|
|
|
2736
2839
|
returns the same token. `token.invalidate(rejected, ctx, { principal })`
|
|
2737
2840
|
receives the principal the rejected token was minted for.
|
|
2738
2841
|
- Catalog listing needs an admitted caller like any call, and its cache stays
|
|
2739
|
-
partitioned per caller.
|
|
2740
|
-
|
|
2842
|
+
partitioned per caller. An operator status/catalog check forwards that
|
|
2843
|
+
request's admitted caller under the same `accept` policy and refusal rules
|
|
2844
|
+
as a call. It checks the resolver, custom `fetch` and downstream connection
|
|
2845
|
+
and catalog as that operator; it never substitutes another identity.
|
|
2846
|
+
- Without an admitted caller, status returns the non-error `per_caller` state
|
|
2847
|
+
with "Authenticates as each caller; verified on use." It does not resolve a
|
|
2848
|
+
token or contact the downstream. Calls and catalog reads still refuse a
|
|
2849
|
+
missing caller with `auth_required`. An admitted caller who fails `accept`
|
|
2850
|
+
receives the same refusal from status as from a call. The operator page
|
|
2851
|
+
offers no secret-configuration diagnosis or fix prompt for this refusal.
|
|
2852
|
+
`per_caller` is an additive member of the public `ConnectorStatus["state"]`
|
|
2853
|
+
union; consumers with exhaustive state handling must account for it.
|
|
2741
2854
|
- The connector stays shared. Connecta keeps no per-principal credential state
|
|
2742
2855
|
and never stores, logs or describes the principal or the token. `describe()`
|
|
2743
2856
|
reports `mode: "request"` as for any request resolver.
|
|
2857
|
+
- The resolver's returned token is registered as a credential: every eight-unit
|
|
2858
|
+
run of it is withheld from all agent output in that request. An unsigned
|
|
2859
|
+
principal reference must therefore be opaque, such as the principal id or a
|
|
2860
|
+
random handle. Never return an email such as `alice@example.com` or another
|
|
2861
|
+
domain-bearing string that also appears in the deployment's own names.
|
|
2744
2862
|
|
|
2745
2863
|
#### Over a Workers service binding
|
|
2746
2864
|
|
|
@@ -2777,9 +2895,11 @@ could name any person. A signature verified with a deployment-held key is also
|
|
|
2777
2895
|
safe on a public route.
|
|
2778
2896
|
|
|
2779
2897
|
`fetch` carries every MCP request, including handshakes, catalog reads, calls,
|
|
2780
|
-
writes and session close. Global fetch is never used for that connector.
|
|
2781
|
-
|
|
2782
|
-
|
|
2898
|
+
writes and session close. Global fetch is never used for that connector. RPC
|
|
2899
|
+
responses returned by this fetch are disposed when the owning request ends,
|
|
2900
|
+
including responses that arrive after cancellation; their bodies remain
|
|
2901
|
+
available during that request. The configured `url` stays the logical origin:
|
|
2902
|
+
its HTTPS rule, cleartext refusal, redirect policy and same-origin redirect checks apply unchanged. A request for
|
|
2783
2903
|
any other origin is refused before it reaches `fetch`. Each request, writes
|
|
2784
2904
|
included, is handed to `fetch` once with `redirect: "manual"`, and a dispatched
|
|
2785
2905
|
write is never sent again, so `fetch` must not retry or follow redirects. On
|
|
@@ -3000,10 +3120,6 @@ The encoding lattice is exactly this, and anything outside it is out of scope:
|
|
|
3000
3120
|
lattice, so redaction is not a defense against a downstream that reshapes a
|
|
3001
3121
|
value on purpose.
|
|
3002
3122
|
|
|
3003
|
-
`test/sent-secret-output-boundary.test.ts` holds the evidence, including its
|
|
3004
|
-
`review round 3`, `review round 4` and `review round 5` blocks for these limits;
|
|
3005
|
-
`test/writeonly-wire-redaction.node.test.ts` runs the QuickJS guest cases.
|
|
3006
|
-
|
|
3007
3123
|
### Source and tests
|
|
3008
3124
|
|
|
3009
3125
|
[Decision 0007](https://github.com/zackbart/connecta/blob/main/decisions/0007-agent-pool-layout.md)
|
|
@@ -3026,8 +3142,6 @@ Downstream OAuth implementation and evidence are in
|
|
|
3026
3142
|
[downstream-oauth.ts](https://github.com/zackbart/connecta/blob/main/src/auth/downstream-oauth.ts),
|
|
3027
3143
|
[static-oauth.ts](https://github.com/zackbart/connecta/blob/main/src/auth/static-oauth.ts),
|
|
3028
3144
|
[OAuth connect tests](https://github.com/zackbart/connecta/blob/main/test/oauth-connect.test.ts),
|
|
3029
|
-
[callback fencing](https://github.com/zackbart/connecta/blob/main/test/oauth-callback-fencing.test.ts),
|
|
3030
|
-
[refresh leases](https://github.com/zackbart/connecta/blob/main/test/oauth-refresh-lease.test.ts),
|
|
3031
3145
|
and [API OAuth tests](https://github.com/zackbart/connecta/blob/main/test/api-oauth.test.ts).
|
|
3032
3146
|
Use the test pointers within each section for narrower failure cases.
|
|
3033
3147
|
|