@relaycast/engine 12.2.0 → 12.3.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/dist/adapters/actor/credential-tag.d.ts +14 -0
- package/dist/adapters/actor/credential-tag.d.ts.map +1 -0
- package/dist/adapters/actor/credential-tag.js +30 -0
- package/dist/adapters/actor/credential-tag.js.map +1 -0
- package/dist/adapters/actor/database.d.ts +50 -0
- package/dist/adapters/actor/database.d.ts.map +1 -0
- package/dist/adapters/actor/database.js +86 -0
- package/dist/adapters/actor/database.js.map +1 -0
- package/dist/adapters/actor/ephemeral-outbox.d.ts +16 -0
- package/dist/adapters/actor/ephemeral-outbox.d.ts.map +1 -0
- package/dist/adapters/actor/ephemeral-outbox.js +53 -0
- package/dist/adapters/actor/ephemeral-outbox.js.map +1 -0
- package/dist/adapters/actor/event-queue.d.ts +23 -0
- package/dist/adapters/actor/event-queue.d.ts.map +1 -0
- package/dist/adapters/actor/event-queue.js +31 -0
- package/dist/adapters/actor/event-queue.js.map +1 -0
- package/dist/adapters/actor/files.d.ts +66 -0
- package/dist/adapters/actor/files.d.ts.map +1 -0
- package/dist/adapters/actor/files.js +83 -0
- package/dist/adapters/actor/files.js.map +1 -0
- package/dist/adapters/actor/http.d.ts +19 -0
- package/dist/adapters/actor/http.d.ts.map +1 -0
- package/dist/adapters/actor/http.js +2 -0
- package/dist/adapters/actor/http.js.map +1 -0
- package/dist/adapters/actor/index.d.ts +90 -0
- package/dist/adapters/actor/index.d.ts.map +1 -0
- package/dist/adapters/actor/index.js +299 -0
- package/dist/adapters/actor/index.js.map +1 -0
- package/dist/adapters/actor/kv.d.ts +21 -0
- package/dist/adapters/actor/kv.d.ts.map +1 -0
- package/dist/adapters/actor/kv.js +33 -0
- package/dist/adapters/actor/kv.js.map +1 -0
- package/dist/adapters/actor/migrations.d.ts +15 -0
- package/dist/adapters/actor/migrations.d.ts.map +1 -0
- package/dist/adapters/actor/migrations.generated.d.ts +5 -0
- package/dist/adapters/actor/migrations.generated.d.ts.map +1 -0
- package/dist/adapters/actor/migrations.generated.js +842 -0
- package/dist/adapters/actor/migrations.generated.js.map +1 -0
- package/dist/adapters/actor/migrations.js +32 -0
- package/dist/adapters/actor/migrations.js.map +1 -0
- package/dist/adapters/node/files.d.ts +2 -0
- package/dist/adapters/node/files.d.ts.map +1 -1
- package/dist/adapters/node/files.js +31 -3
- package/dist/adapters/node/files.js.map +1 -1
- package/dist/adapters/node/index.js +1 -1
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/auth/credentialTags.d.ts +43 -0
- package/dist/auth/credentialTags.d.ts.map +1 -0
- package/dist/auth/credentialTags.js +106 -0
- package/dist/auth/credentialTags.js.map +1 -0
- package/dist/auth/credentials.d.ts +103 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +147 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/index.d.ts +7 -4
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +115 -61
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/tokenKind.d.ts +17 -26
- package/dist/auth/tokenKind.d.ts.map +1 -1
- package/dist/auth/tokenKind.js +17 -46
- package/dist/auth/tokenKind.js.map +1 -1
- package/dist/auth/workspaceExpiry.d.ts +2 -0
- package/dist/auth/workspaceExpiry.d.ts.map +1 -1
- package/dist/auth/workspaceExpiry.js +7 -0
- package/dist/auth/workspaceExpiry.js.map +1 -1
- package/dist/bin/secretEnv.d.ts +17 -0
- package/dist/bin/secretEnv.d.ts.map +1 -0
- package/dist/bin/secretEnv.js +33 -0
- package/dist/bin/secretEnv.js.map +1 -0
- package/dist/bin/serve.js +42 -4
- package/dist/bin/serve.js.map +1 -1
- package/dist/config/credentialEnv.d.ts +19 -0
- package/dist/config/credentialEnv.d.ts.map +1 -0
- package/dist/config/credentialEnv.js +53 -0
- package/dist/config/credentialEnv.js.map +1 -0
- package/dist/db/migrations/0078_dm_participant_read_cursor.sql +15 -0
- package/dist/db/migrations/0079_credential_upgrades.sql +17 -0
- package/dist/db/schema.d.ts +183 -2
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +23 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/engine/a2a.d.ts +1 -1
- package/dist/engine/a2a.d.ts.map +1 -1
- package/dist/engine/a2a.js +2 -2
- package/dist/engine/a2a.js.map +1 -1
- package/dist/engine/a2aEgress.d.ts +3 -2
- package/dist/engine/a2aEgress.d.ts.map +1 -1
- package/dist/engine/a2aEgress.js +5 -4
- package/dist/engine/a2aEgress.js.map +1 -1
- package/dist/engine/action.d.ts +12 -0
- package/dist/engine/action.d.ts.map +1 -1
- package/dist/engine/action.js +45 -1
- package/dist/engine/action.js.map +1 -1
- package/dist/engine/agent.d.ts.map +1 -1
- package/dist/engine/agent.js +2 -1
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/agentIdentity.d.ts.map +1 -1
- package/dist/engine/agentIdentity.js +2 -1
- package/dist/engine/agentIdentity.js.map +1 -1
- package/dist/engine/credentialUpgrade.d.ts +48 -0
- package/dist/engine/credentialUpgrade.d.ts.map +1 -0
- package/dist/engine/credentialUpgrade.js +176 -0
- package/dist/engine/credentialUpgrade.js.map +1 -0
- package/dist/engine/delivery.d.ts.map +1 -1
- package/dist/engine/delivery.js +70 -31
- package/dist/engine/delivery.js.map +1 -1
- package/dist/engine/eventDispatch.d.ts.map +1 -1
- package/dist/engine/eventDispatch.js +3 -2
- package/dist/engine/eventDispatch.js.map +1 -1
- package/dist/engine/eventSubscription.d.ts +4 -4
- package/dist/engine/file.d.ts +8 -0
- package/dist/engine/file.d.ts.map +1 -1
- package/dist/engine/file.js +18 -5
- package/dist/engine/file.js.map +1 -1
- package/dist/engine/inboundWebhook.d.ts +2 -0
- package/dist/engine/inboundWebhook.d.ts.map +1 -1
- package/dist/engine/inboundWebhook.js +10 -4
- package/dist/engine/inboundWebhook.js.map +1 -1
- package/dist/engine/inbox.d.ts.map +1 -1
- package/dist/engine/inbox.js +10 -5
- package/dist/engine/inbox.js.map +1 -1
- package/dist/engine/internalAdmin.d.ts +80 -0
- package/dist/engine/internalAdmin.d.ts.map +1 -0
- package/dist/engine/internalAdmin.js +329 -0
- package/dist/engine/internalAdmin.js.map +1 -0
- package/dist/engine/invocationCompletion.d.ts.map +1 -1
- package/dist/engine/invocationCompletion.js +23 -5
- package/dist/engine/invocationCompletion.js.map +1 -1
- package/dist/engine/node.d.ts +38 -1
- package/dist/engine/node.d.ts.map +1 -1
- package/dist/engine/node.js +166 -11
- package/dist/engine/node.js.map +1 -1
- package/dist/engine/nodeContext.d.ts +2 -1
- package/dist/engine/nodeContext.d.ts.map +1 -1
- package/dist/engine/nodeContext.js +1 -1
- package/dist/engine/nodeContext.js.map +1 -1
- package/dist/engine/nodeDeliver.d.ts +2 -1
- package/dist/engine/nodeDeliver.d.ts.map +1 -1
- package/dist/engine/nodeDeliver.js +1 -1
- package/dist/engine/nodeDeliver.js.map +1 -1
- package/dist/engine/observerToken.d.ts +4 -0
- package/dist/engine/observerToken.d.ts.map +1 -1
- package/dist/engine/observerToken.js +14 -5
- package/dist/engine/observerToken.js.map +1 -1
- package/dist/engine/receipt.d.ts +100 -0
- package/dist/engine/receipt.d.ts.map +1 -1
- package/dist/engine/receipt.js +12 -0
- package/dist/engine/receipt.js.map +1 -1
- package/dist/engine/taskInvocation.d.ts +1 -1
- package/dist/engine/tokenRotate.d.ts.map +1 -1
- package/dist/engine/tokenRotate.js +4 -3
- package/dist/engine/tokenRotate.js.map +1 -1
- package/dist/engine/workspace.d.ts +8 -2
- package/dist/engine/workspace.d.ts.map +1 -1
- package/dist/engine/workspace.js +70 -21
- package/dist/engine/workspace.js.map +1 -1
- package/dist/engine/wsAuth.d.ts.map +1 -1
- package/dist/engine/wsAuth.js +14 -3
- package/dist/engine/wsAuth.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +31 -0
- package/dist/engine.js.map +1 -1
- package/dist/entrypoints/node.d.ts +3 -1
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +33 -1
- package/dist/entrypoints/node.js.map +1 -1
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/gateway.d.ts +11 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +16 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/credentialNotice.d.ts +32 -0
- package/dist/lib/credentialNotice.d.ts.map +1 -0
- package/dist/lib/credentialNotice.js +76 -0
- package/dist/lib/credentialNotice.js.map +1 -0
- package/dist/lib/fileTokens.d.ts +30 -0
- package/dist/lib/fileTokens.d.ts.map +1 -0
- package/dist/lib/fileTokens.js +76 -0
- package/dist/lib/fileTokens.js.map +1 -0
- package/dist/lib/httpError.d.ts +1 -1
- package/dist/lib/httpResponse.d.ts +6 -6
- package/dist/middleware/admission.d.ts +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +22 -31
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +1 -1
- package/dist/middleware/logger.d.ts.map +1 -1
- package/dist/middleware/logger.js +4 -1
- package/dist/middleware/logger.js.map +1 -1
- package/dist/ports/database.d.ts.map +1 -1
- package/dist/ports/database.js +8 -2
- package/dist/ports/database.js.map +1 -1
- package/dist/ports/files.d.ts +7 -1
- package/dist/ports/files.d.ts.map +1 -1
- package/dist/ports/index.d.ts +64 -1
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +4 -0
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/telemetry.d.ts +1 -0
- package/dist/ports/telemetry.d.ts.map +1 -1
- package/dist/ports/telemetry.js +1 -0
- package/dist/ports/telemetry.js.map +1 -1
- package/dist/routes/action.d.ts.map +1 -1
- package/dist/routes/action.js +2 -1
- package/dist/routes/action.js.map +1 -1
- package/dist/routes/credential.d.ts +4 -0
- package/dist/routes/credential.d.ts.map +1 -0
- package/dist/routes/credential.js +97 -0
- package/dist/routes/credential.js.map +1 -0
- package/dist/routes/file.js +10 -4
- package/dist/routes/file.js.map +1 -1
- package/dist/routes/inboundWebhook.d.ts.map +1 -1
- package/dist/routes/inboundWebhook.js +11 -2
- package/dist/routes/inboundWebhook.js.map +1 -1
- package/dist/routes/internal.d.ts +14 -0
- package/dist/routes/internal.d.ts.map +1 -0
- package/dist/routes/internal.js +157 -0
- package/dist/routes/internal.js.map +1 -0
- package/dist/routes/node.d.ts.map +1 -1
- package/dist/routes/node.js +44 -2
- package/dist/routes/node.js.map +1 -1
- package/dist/routes/observerToken.js +1 -1
- package/dist/routes/observerToken.js.map +1 -1
- package/dist/routes/reaction.d.ts.map +1 -1
- package/dist/routes/reaction.js +3 -2
- package/dist/routes/reaction.js.map +1 -1
- package/dist/routes/receipt.d.ts.map +1 -1
- package/dist/routes/receipt.js +2 -1
- package/dist/routes/receipt.js.map +1 -1
- package/dist/routes/workspace.d.ts.map +1 -1
- package/dist/routes/workspace.js +12 -1
- package/dist/routes/workspace.js.map +1 -1
- package/package.json +12 -3
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { AR_KIND_CODES, AR_SECRET_BYTES, LEGACY_CREDENTIAL_PREFIXES, encodeArCredential, isArWorkspaceId, parseCredential, } from '@relaycast/types';
|
|
2
|
+
import { randomHex } from '../lib/crypto.js';
|
|
3
|
+
export { parseCredential };
|
|
4
|
+
/** Why a deployment that mints `ar_` credentials refuses a workspace id. */
|
|
5
|
+
export const AR_WORKSPACE_ID_REQUIRED = 'workspace ids must be snowflakes on deployments that mint ar_ credentials';
|
|
6
|
+
/**
|
|
7
|
+
* Minting an `ar_` credential for a workspace id that is not a 64-bit
|
|
8
|
+
* snowflake. Routes check ids before writing; this is the backstop, and it
|
|
9
|
+
* answers `400 invalid_request`.
|
|
10
|
+
*/
|
|
11
|
+
export class WorkspaceIdNotSnowflakeError extends Error {
|
|
12
|
+
workspaceId;
|
|
13
|
+
code = 'invalid_request';
|
|
14
|
+
status = 400;
|
|
15
|
+
clientSafe = true;
|
|
16
|
+
constructor(workspaceId) {
|
|
17
|
+
super(AR_WORKSPACE_ID_REQUIRED);
|
|
18
|
+
this.workspaceId = workspaceId;
|
|
19
|
+
this.name = 'WorkspaceIdNotSnowflakeError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Random secret bytes per `legacy` kind (the established lengths). */
|
|
23
|
+
const LEGACY_SECRET_BYTES = {
|
|
24
|
+
workspace: 16,
|
|
25
|
+
agent: 16,
|
|
26
|
+
node: 24,
|
|
27
|
+
observer: 24,
|
|
28
|
+
webhook: 24,
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Parse an `ar_` credential, for gateways that route by it. Proves only shape
|
|
32
|
+
* and checksum; verify its tag with `createCredentialTagSigner(...).verify`.
|
|
33
|
+
*/
|
|
34
|
+
export function parseArCredential(token) {
|
|
35
|
+
const parsed = parseCredential(token);
|
|
36
|
+
return parsed?.family === 'ar'
|
|
37
|
+
? { kind: parsed.kind, workspaceId: parsed.workspaceId, tag: parsed.tag, keyVersion: parsed.keyVersion }
|
|
38
|
+
: undefined;
|
|
39
|
+
}
|
|
40
|
+
/** Human-readable shape of a credential kind in the family a deployment mints, for error messages. */
|
|
41
|
+
export function credentialShape(kind, format) {
|
|
42
|
+
return format === 'ar' ? `ar_${AR_KIND_CODES[kind]}_...` : `${LEGACY_CREDENTIAL_PREFIXES[kind]}...`;
|
|
43
|
+
}
|
|
44
|
+
function hexToBytes(hex) {
|
|
45
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
46
|
+
for (let i = 0; i < bytes.length; i += 1)
|
|
47
|
+
bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
48
|
+
return bytes;
|
|
49
|
+
}
|
|
50
|
+
const settings = new WeakMap();
|
|
51
|
+
/**
|
|
52
|
+
* Bind the family a deployment mints, and its tagger, to its database handle.
|
|
53
|
+
* Every engine path that mints a credential holds the handle, so the settings
|
|
54
|
+
* travel with it (the same binding pattern as node liveness).
|
|
55
|
+
*/
|
|
56
|
+
export function configureCredentials(db, next) {
|
|
57
|
+
if (next.format === 'ar' && !next.tagger) {
|
|
58
|
+
throw new Error("credentialFormat 'ar' needs a credentialTagger");
|
|
59
|
+
}
|
|
60
|
+
const bound = settings.get(db);
|
|
61
|
+
if (bound !== undefined && (bound.format !== next.format || bound.tagger !== next.tagger)) {
|
|
62
|
+
throw new Error(`This database handle already mints ${bound.format} credentials; one handle serves one credential configuration`);
|
|
63
|
+
}
|
|
64
|
+
settings.set(db, next);
|
|
65
|
+
}
|
|
66
|
+
const arOnlyHandles = new WeakSet();
|
|
67
|
+
/**
|
|
68
|
+
* Accept only `ar_` credentials on `db`'s deployment: legacy ones are refused
|
|
69
|
+
* with 401, `POST /v1/credentials/upgrade` is not served and no response is
|
|
70
|
+
* marked deprecated. Inherent to the workspace actor runtime, whose
|
|
71
|
+
* deployments never issued legacy credentials; call before `createEngine`.
|
|
72
|
+
*/
|
|
73
|
+
export function restrictToArCredentials(db) {
|
|
74
|
+
arOnlyHandles.add(db);
|
|
75
|
+
}
|
|
76
|
+
/** Whether `db`'s deployment accepts only `ar_` credentials. */
|
|
77
|
+
export function acceptsOnlyAr(db) {
|
|
78
|
+
return arOnlyHandles.has(db);
|
|
79
|
+
}
|
|
80
|
+
/** Carry `db`'s credential settings onto a derived handle (a transaction). */
|
|
81
|
+
export function inheritCredentials(derived, db) {
|
|
82
|
+
const bound = settings.get(db);
|
|
83
|
+
if (bound)
|
|
84
|
+
configureCredentials(derived, bound);
|
|
85
|
+
if (arOnlyHandles.has(db))
|
|
86
|
+
arOnlyHandles.add(derived);
|
|
87
|
+
}
|
|
88
|
+
/** The credential family `db`'s deployment mints; `legacy` unless configured otherwise. */
|
|
89
|
+
export function credentialFormat(db) {
|
|
90
|
+
return settings.get(db)?.format ?? 'legacy';
|
|
91
|
+
}
|
|
92
|
+
/** The deployment's tagger, when it can mint `ar_` credentials. */
|
|
93
|
+
export function credentialTagger(db) {
|
|
94
|
+
return settings.get(db)?.tagger;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Every family a credential derived for `workspaceId` may have been committed
|
|
98
|
+
* in, the deployment's current one first: `legacy`, and `ar` under each tag
|
|
99
|
+
* the deployment's tagger knows for the workspace. A replay derives each, so
|
|
100
|
+
* one retried after a family switch or a keyring rotation still recovers what
|
|
101
|
+
* the first attempt committed.
|
|
102
|
+
*/
|
|
103
|
+
export async function derivationFamilies(db, workspaceId) {
|
|
104
|
+
// A workspace id that is not a snowflake cannot carry an ar_ credential.
|
|
105
|
+
const tagger = isArWorkspaceId(workspaceId) ? credentialTagger(db) : undefined;
|
|
106
|
+
const ar = tagger ? (await tagger.tags(workspaceId)).map((tag) => ({ format: 'ar', tag })) : [];
|
|
107
|
+
return credentialFormat(db) === 'ar' ? [...ar, { format: 'legacy' }] : [{ format: 'legacy' }, ...ar];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Build a credential from caller-supplied hex secret material (a random value
|
|
111
|
+
* or a deterministic HMAC/SHA-256 digest), at least as long as the family's
|
|
112
|
+
* secret. An `ar_` credential carries `tag`, by default the deployment's
|
|
113
|
+
* current tag for the workspace.
|
|
114
|
+
*/
|
|
115
|
+
export async function credentialFromHex(db, format, kind, workspaceId, hex, tag) {
|
|
116
|
+
if (!/^[0-9a-f]+$/.test(hex))
|
|
117
|
+
throw new Error('Credential secret material must be lowercase hex');
|
|
118
|
+
if (format === 'ar') {
|
|
119
|
+
if (!isArWorkspaceId(workspaceId))
|
|
120
|
+
throw new WorkspaceIdNotSnowflakeError(workspaceId);
|
|
121
|
+
if (hex.length < AR_SECRET_BYTES * 2)
|
|
122
|
+
throw new Error('Credential secret material is too short');
|
|
123
|
+
const tagger = credentialTagger(db);
|
|
124
|
+
if (!tag && !tagger)
|
|
125
|
+
throw new Error('Minting an ar_ credential needs EngineConfig.credentialTagger');
|
|
126
|
+
return encodeArCredential({
|
|
127
|
+
kind,
|
|
128
|
+
workspaceId,
|
|
129
|
+
tag: tag ?? await tagger.tag(workspaceId),
|
|
130
|
+
secret: hexToBytes(hex.slice(0, AR_SECRET_BYTES * 2)),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const length = LEGACY_SECRET_BYTES[kind] * 2;
|
|
134
|
+
if (hex.length < length)
|
|
135
|
+
throw new Error('Credential secret material is too short');
|
|
136
|
+
return `${LEGACY_CREDENTIAL_PREFIXES[kind]}${hex.slice(0, length)}`;
|
|
137
|
+
}
|
|
138
|
+
/** Mint a fresh random credential of `kind` for `workspaceId`, in `format`. */
|
|
139
|
+
export function mintCredential(db, format, kind, workspaceId) {
|
|
140
|
+
const bytes = format === 'ar' ? AR_SECRET_BYTES : LEGACY_SECRET_BYTES[kind];
|
|
141
|
+
return credentialFromHex(db, format, kind, workspaceId, randomHex(bytes));
|
|
142
|
+
}
|
|
143
|
+
/** Mint a fresh credential in the family bound to `db`. */
|
|
144
|
+
export function issueCredential(db, kind, workspaceId) {
|
|
145
|
+
return mintCredential(db, credentialFormat(db), kind, workspaceId);
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/auth/credentials.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -6,10 +6,13 @@ export declare function hashToken(token: string): Promise<string>;
|
|
|
6
6
|
/**
|
|
7
7
|
* The built-in, self-host authentication provider.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Workspace, agent, node and observer credentials of either family
|
|
10
|
+
* (`auth/credentials.ts`) are SHA-256 hashed and looked up in the table their
|
|
11
|
+
* kind names. An `ar_` credential is looked up within the workspace it names,
|
|
12
|
+
* in one indexed query. A legacy credential replaced through
|
|
13
|
+
* `POST /v1/credentials/upgrade` keeps authenticating during its grace
|
|
14
|
+
* (`credential_upgrades`). The cloud product replaces this with a provider
|
|
15
|
+
* backed by its own accounts/billing system.
|
|
13
16
|
*/
|
|
14
17
|
export declare class SqliteApiKeyAuthProvider implements AuthProvider {
|
|
15
18
|
hashToken(token: string): Promise<string>;
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAMrD,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAE9B,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAExD;AAmBD;;;;;;;;;;GAUG;AACH,qBAAa,wBAAyB,YAAW,YAAY;IAC3D,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAInC,YAAY,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,CAAC;QAAC,EAAE,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;CAoBrG"}
|
package/dist/auth/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { and, eq, gt } from 'drizzle-orm';
|
|
2
|
-
import { workspaces, agents, nodes } from '../db/schema.js';
|
|
1
|
+
import { and, eq, gt, or } from 'drizzle-orm';
|
|
2
|
+
import { workspaces, agents, nodes, observerTokens } from '../db/schema.js';
|
|
3
3
|
import { sha256Hex } from '../lib/crypto.js';
|
|
4
|
-
import { getActiveObserverTokenByHash } from '../engine/observerToken.js';
|
|
4
|
+
import { activeObserverTokenCondition, getActiveObserverTokenByHash, noteObserverTokenUse, } from '../engine/observerToken.js';
|
|
5
5
|
import { parseAuthToken, validateTokenRequirement } from './tokenKind.js';
|
|
6
|
+
import { credentialFormat } from './credentials.js';
|
|
7
|
+
import { upgradedLegacyCredential } from '../engine/credentialUpgrade.js';
|
|
6
8
|
import { isWorkspaceExpired, workspaceExpiredAuthResult } from './workspaceExpiry.js';
|
|
7
9
|
export { isWorkspaceExpired, authenticateUnexpired, workspaceExpiredAuthResult, WORKSPACE_EXPIRED_CODE, WORKSPACE_EXPIRED_MESSAGE, } from './workspaceExpiry.js';
|
|
8
10
|
/** SHA-256 hash of a raw token to its stored form. */
|
|
@@ -25,10 +27,13 @@ function resolved(workspace, extra = {}) {
|
|
|
25
27
|
/**
|
|
26
28
|
* The built-in, self-host authentication provider.
|
|
27
29
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* Workspace, agent, node and observer credentials of either family
|
|
31
|
+
* (`auth/credentials.ts`) are SHA-256 hashed and looked up in the table their
|
|
32
|
+
* kind names. An `ar_` credential is looked up within the workspace it names,
|
|
33
|
+
* in one indexed query. A legacy credential replaced through
|
|
34
|
+
* `POST /v1/credentials/upgrade` keeps authenticating during its grace
|
|
35
|
+
* (`credential_upgrades`). The cloud product replaces this with a provider
|
|
36
|
+
* backed by its own accounts/billing system.
|
|
32
37
|
*/
|
|
33
38
|
export class SqliteApiKeyAuthProvider {
|
|
34
39
|
hashToken(token) {
|
|
@@ -40,67 +45,116 @@ export class SqliteApiKeyAuthProvider {
|
|
|
40
45
|
if (!parsedToken) {
|
|
41
46
|
return unauthorized('Invalid token format');
|
|
42
47
|
}
|
|
43
|
-
const requirement = validateTokenRequirement(parsedToken.kind, require);
|
|
48
|
+
const requirement = validateTokenRequirement(parsedToken.kind, require, credentialFormat(db));
|
|
44
49
|
if (!requirement.ok) {
|
|
45
50
|
return unauthorized(requirement.message, requirement.code);
|
|
46
51
|
}
|
|
47
52
|
const hash = await hashToken(token);
|
|
48
|
-
if (parsedToken.
|
|
49
|
-
|
|
50
|
-
let [workspace] = await db.select().from(workspaces).where(eq(workspaces.apiKeyHash, hash));
|
|
51
|
-
if (!workspace) {
|
|
52
|
-
// Superseded key inside its rotation grace window. A rotation with
|
|
53
|
-
// zero grace writes no usable previous slot, so a compromised key
|
|
54
|
-
// never lands here.
|
|
55
|
-
[workspace] = await db
|
|
56
|
-
.select()
|
|
57
|
-
.from(workspaces)
|
|
58
|
-
.where(and(eq(workspaces.previousApiKeyHash, hash), gt(workspaces.previousApiKeyExpiresAt, new Date())));
|
|
59
|
-
}
|
|
60
|
-
if (!workspace)
|
|
61
|
-
return unauthorized('Invalid API key');
|
|
62
|
-
return resolved(workspace);
|
|
53
|
+
if (parsedToken.workspaceId !== undefined) {
|
|
54
|
+
return authenticateAr(db, parsedToken.kind, parsedToken.workspaceId, hash);
|
|
63
55
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return unauthorized('Workspace not found');
|
|
83
|
-
return resolved(workspace, { agent });
|
|
84
|
-
}
|
|
85
|
-
if (parsedToken.kind === 'node') {
|
|
86
|
-
const [node] = await db.select().from(nodes).where(eq(nodes.tokenHash, hash));
|
|
87
|
-
if (!node)
|
|
88
|
-
return unauthorized('Invalid node token', 'node_token_invalid');
|
|
89
|
-
const [workspace] = await db.select().from(workspaces).where(eq(workspaces.id, node.workspaceId));
|
|
90
|
-
if (!workspace)
|
|
91
|
-
return unauthorized('Workspace not found');
|
|
92
|
-
return resolved(workspace, { node });
|
|
56
|
+
const legacy = await authenticateLegacy(db, parsedToken.kind, hash);
|
|
57
|
+
if (legacy.ok || legacy.code === 'workspace_expired')
|
|
58
|
+
return legacy;
|
|
59
|
+
return await authenticateUpgradedLegacy(db, parsedToken.kind, hash) ?? legacy;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function authenticateLegacy(db, kind, hash) {
|
|
63
|
+
if (kind === 'workspace') {
|
|
64
|
+
// Current slot first — same shape as the agent-token lookup below.
|
|
65
|
+
let [workspace] = await db.select().from(workspaces).where(eq(workspaces.apiKeyHash, hash));
|
|
66
|
+
if (!workspace) {
|
|
67
|
+
// Superseded key inside its rotation grace window. A rotation with
|
|
68
|
+
// zero grace writes no usable previous slot, so a compromised key
|
|
69
|
+
// never lands here.
|
|
70
|
+
[workspace] = await db
|
|
71
|
+
.select()
|
|
72
|
+
.from(workspaces)
|
|
73
|
+
.where(and(eq(workspaces.previousApiKeyHash, hash), gt(workspaces.previousApiKeyExpiresAt, new Date())));
|
|
93
74
|
}
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
75
|
+
if (!workspace)
|
|
76
|
+
return unauthorized('Invalid API key');
|
|
77
|
+
return resolved(workspace);
|
|
78
|
+
}
|
|
79
|
+
if (kind === 'agent') {
|
|
80
|
+
// Current slot first — the common case is a token that has not been
|
|
81
|
+
// rotated out from under this caller.
|
|
82
|
+
let [agent] = await db.select().from(agents).where(eq(agents.tokenHash, hash));
|
|
83
|
+
if (!agent) {
|
|
84
|
+
// Fall back to the previous slot inside its grace window. This is the
|
|
85
|
+
// credential a caller that lost a concurrent self-rollover race was
|
|
86
|
+
// handed (relay#1542); it must remain live long enough for that caller
|
|
87
|
+
// to upgrade to a persistent session.
|
|
88
|
+
[agent] = await db
|
|
89
|
+
.select()
|
|
90
|
+
.from(agents)
|
|
91
|
+
.where(and(eq(agents.previousTokenHash, hash), gt(agents.previousTokenExpiresAt, new Date())));
|
|
102
92
|
}
|
|
103
|
-
|
|
93
|
+
if (!agent)
|
|
94
|
+
return unauthorized('Invalid agent token', 'agent_token_invalid');
|
|
95
|
+
const [workspace] = await db.select().from(workspaces).where(eq(workspaces.id, agent.workspaceId));
|
|
96
|
+
if (!workspace)
|
|
97
|
+
return unauthorized('Workspace not found');
|
|
98
|
+
return resolved(workspace, { agent });
|
|
99
|
+
}
|
|
100
|
+
if (kind === 'node') {
|
|
101
|
+
const [node] = await db.select().from(nodes).where(eq(nodes.tokenHash, hash));
|
|
102
|
+
if (!node)
|
|
103
|
+
return unauthorized('Invalid node token', 'node_token_invalid');
|
|
104
|
+
const [workspace] = await db.select().from(workspaces).where(eq(workspaces.id, node.workspaceId));
|
|
105
|
+
if (!workspace)
|
|
106
|
+
return unauthorized('Workspace not found');
|
|
107
|
+
return resolved(workspace, { node });
|
|
108
|
+
}
|
|
109
|
+
if (kind === 'observer') {
|
|
110
|
+
const observerToken = await getActiveObserverTokenByHash(db, hash);
|
|
111
|
+
if (!observerToken)
|
|
112
|
+
return unauthorized('Invalid observer token', 'observer_token_invalid');
|
|
113
|
+
const [workspace] = await db.select().from(workspaces).where(eq(workspaces.id, observerToken.workspaceId));
|
|
114
|
+
if (!workspace)
|
|
115
|
+
return unauthorized('Workspace not found');
|
|
116
|
+
return resolved(workspace, { observerToken });
|
|
117
|
+
}
|
|
118
|
+
return unauthorized('Invalid token format');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* A legacy credential replaced through `POST /v1/credentials/upgrade`, inside
|
|
122
|
+
* its grace: the principal it was upgraded from, while that principal still
|
|
123
|
+
* holds the `ar_` credential. `undefined` when the hash is no such credential.
|
|
124
|
+
*/
|
|
125
|
+
async function authenticateUpgradedLegacy(db, kind, hash) {
|
|
126
|
+
const upgraded = await upgradedLegacyCredential(db, kind, hash);
|
|
127
|
+
return upgraded ? authenticateAr(db, kind, upgraded.workspaceId, upgraded.arHash) : undefined;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Verify an `ar_` credential: one indexed query against the table its kind
|
|
131
|
+
* names, scoped to the workspace it names, returning the principal and its
|
|
132
|
+
* workspace together. Rotation grace slots match as in the legacy lookups.
|
|
133
|
+
*/
|
|
134
|
+
async function authenticateAr(db, kind, workspaceId, hash) {
|
|
135
|
+
const now = new Date();
|
|
136
|
+
if (kind === 'workspace') {
|
|
137
|
+
const [workspace] = await db.select().from(workspaces).where(and(eq(workspaces.id, workspaceId), or(eq(workspaces.apiKeyHash, hash), and(eq(workspaces.previousApiKeyHash, hash), gt(workspaces.previousApiKeyExpiresAt, now)))));
|
|
138
|
+
return workspace ? resolved(workspace) : unauthorized('Invalid API key');
|
|
139
|
+
}
|
|
140
|
+
if (kind === 'agent') {
|
|
141
|
+
const [row] = await db.select({ agent: agents, workspace: workspaces }).from(agents)
|
|
142
|
+
.innerJoin(workspaces, eq(workspaces.id, agents.workspaceId))
|
|
143
|
+
.where(and(eq(agents.workspaceId, workspaceId), or(eq(agents.tokenHash, hash), and(eq(agents.previousTokenHash, hash), gt(agents.previousTokenExpiresAt, now)))));
|
|
144
|
+
return row ? resolved(row.workspace, { agent: row.agent }) : unauthorized('Invalid agent token', 'agent_token_invalid');
|
|
145
|
+
}
|
|
146
|
+
if (kind === 'node') {
|
|
147
|
+
const [row] = await db.select({ node: nodes, workspace: workspaces }).from(nodes)
|
|
148
|
+
.innerJoin(workspaces, eq(workspaces.id, nodes.workspaceId))
|
|
149
|
+
.where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.tokenHash, hash)));
|
|
150
|
+
return row ? resolved(row.workspace, { node: row.node }) : unauthorized('Invalid node token', 'node_token_invalid');
|
|
104
151
|
}
|
|
152
|
+
const [row] = await db.select({ observerToken: observerTokens, workspace: workspaces }).from(observerTokens)
|
|
153
|
+
.innerJoin(workspaces, eq(workspaces.id, observerTokens.workspaceId))
|
|
154
|
+
.where(and(eq(observerTokens.workspaceId, workspaceId), eq(observerTokens.tokenHash, hash), activeObserverTokenCondition(now)));
|
|
155
|
+
if (!row)
|
|
156
|
+
return unauthorized('Invalid observer token', 'observer_token_invalid');
|
|
157
|
+
noteObserverTokenUse(db, row.observerToken, now);
|
|
158
|
+
return resolved(row.workspace, { observerToken: row.observerToken });
|
|
105
159
|
}
|
|
106
160
|
//# sourceMappingURL=index.js.map
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/tokenKind.d.ts
CHANGED
|
@@ -1,33 +1,24 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
1
|
import type { AuthRequire } from '../ports/auth.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
readonly
|
|
9
|
-
readonly prefix: "at_live_";
|
|
10
|
-
readonly requiredMessage: "Agent token required (at_live_...)";
|
|
11
|
-
};
|
|
12
|
-
readonly node: {
|
|
13
|
-
readonly prefix: "nt_live_";
|
|
14
|
-
readonly requiredMessage: "Node token required (nt_live_...)";
|
|
15
|
-
};
|
|
16
|
-
readonly observer: {
|
|
17
|
-
readonly prefix: "ot_live_";
|
|
18
|
-
readonly requiredMessage: "Observer token required (ot_live_...)";
|
|
19
|
-
};
|
|
2
|
+
import { type CredentialFormat } from './credentials.js';
|
|
3
|
+
declare const tokenKindLabel: {
|
|
4
|
+
readonly workspace: "Workspace key";
|
|
5
|
+
readonly agent: "Agent token";
|
|
6
|
+
readonly node: "Node token";
|
|
7
|
+
readonly observer: "Observer token";
|
|
20
8
|
};
|
|
21
|
-
export type AuthTokenKind = keyof typeof
|
|
22
|
-
|
|
23
|
-
kind:
|
|
9
|
+
export type AuthTokenKind = keyof typeof tokenKindLabel;
|
|
10
|
+
export interface ParsedAuthToken {
|
|
11
|
+
kind: AuthTokenKind;
|
|
24
12
|
token: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
/** The credential's family. */
|
|
14
|
+
family: 'legacy' | 'ar';
|
|
15
|
+
/** The workspace an `ar_` credential names. */
|
|
16
|
+
workspaceId?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Classify an API credential of either family. */
|
|
28
19
|
export declare function parseAuthToken(token: string): ParsedAuthToken | undefined;
|
|
29
20
|
export declare function getAuthTokenKind(token: string): AuthTokenKind | undefined;
|
|
30
|
-
export declare function requiredTokenMessage(kind: Exclude<AuthRequire, 'any' | 'sender'
|
|
21
|
+
export declare function requiredTokenMessage(kind: Exclude<AuthRequire, 'any' | 'sender'>, format: CredentialFormat): string;
|
|
31
22
|
export type AuthRequirementValidation = {
|
|
32
23
|
ok: true;
|
|
33
24
|
} | {
|
|
@@ -35,6 +26,6 @@ export type AuthRequirementValidation = {
|
|
|
35
26
|
code: string;
|
|
36
27
|
message: string;
|
|
37
28
|
};
|
|
38
|
-
export declare function validateTokenRequirement(tokenKind: AuthTokenKind, require: AuthRequire): AuthRequirementValidation;
|
|
29
|
+
export declare function validateTokenRequirement(tokenKind: AuthTokenKind, require: AuthRequire, format: CredentialFormat): AuthRequirementValidation;
|
|
39
30
|
export {};
|
|
40
31
|
//# sourceMappingURL=tokenKind.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokenKind.d.ts","sourceRoot":"","sources":["../../src/auth/tokenKind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"tokenKind.d.ts","sourceRoot":"","sources":["../../src/auth/tokenKind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE3F,QAAA,MAAM,cAAc;;;;;CAKV,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,cAAc,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAMzE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEzE;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,KAAK,GAAG,QAAQ,CAAC,EAC5C,MAAM,EAAE,gBAAgB,GACvB,MAAM,CAER;AAeD,MAAM,MAAM,yBAAyB,GACjC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,gBAAgB,GACvB,yBAAyB,CA+B3B"}
|
package/dist/auth/tokenKind.js
CHANGED
|
@@ -1,53 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const
|
|
3
|
-
workspace:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
agent: {
|
|
8
|
-
prefix: 'at_live_',
|
|
9
|
-
requiredMessage: 'Agent token required (at_live_...)',
|
|
10
|
-
},
|
|
11
|
-
node: {
|
|
12
|
-
prefix: 'nt_live_',
|
|
13
|
-
requiredMessage: 'Node token required (nt_live_...)',
|
|
14
|
-
},
|
|
15
|
-
observer: {
|
|
16
|
-
prefix: 'ot_live_',
|
|
17
|
-
requiredMessage: 'Observer token required (ot_live_...)',
|
|
18
|
-
},
|
|
1
|
+
import { credentialShape, parseCredential } from './credentials.js';
|
|
2
|
+
const tokenKindLabel = {
|
|
3
|
+
workspace: 'Workspace key',
|
|
4
|
+
agent: 'Agent token',
|
|
5
|
+
node: 'Node token',
|
|
6
|
+
observer: 'Observer token',
|
|
19
7
|
};
|
|
20
|
-
|
|
21
|
-
.string()
|
|
22
|
-
.startsWith(tokenKindConfig.workspace.prefix)
|
|
23
|
-
.transform((token) => ({ kind: 'workspace', token }));
|
|
24
|
-
const agentTokenSchema = z
|
|
25
|
-
.string()
|
|
26
|
-
.startsWith(tokenKindConfig.agent.prefix)
|
|
27
|
-
.transform((token) => ({ kind: 'agent', token }));
|
|
28
|
-
const nodeTokenSchema = z
|
|
29
|
-
.string()
|
|
30
|
-
.startsWith(tokenKindConfig.node.prefix)
|
|
31
|
-
.transform((token) => ({ kind: 'node', token }));
|
|
32
|
-
const observerTokenSchema = z
|
|
33
|
-
.string()
|
|
34
|
-
.startsWith(tokenKindConfig.observer.prefix)
|
|
35
|
-
.transform((token) => ({ kind: 'observer', token }));
|
|
36
|
-
export const authTokenSchema = z.union([
|
|
37
|
-
workspaceTokenSchema,
|
|
38
|
-
agentTokenSchema,
|
|
39
|
-
nodeTokenSchema,
|
|
40
|
-
observerTokenSchema,
|
|
41
|
-
]);
|
|
8
|
+
/** Classify an API credential of either family. */
|
|
42
9
|
export function parseAuthToken(token) {
|
|
43
|
-
const parsed =
|
|
44
|
-
|
|
10
|
+
const parsed = parseCredential(token);
|
|
11
|
+
if (!parsed || parsed.kind === 'webhook')
|
|
12
|
+
return undefined;
|
|
13
|
+
return parsed.family === 'ar'
|
|
14
|
+
? { kind: parsed.kind, token, family: 'ar', workspaceId: parsed.workspaceId }
|
|
15
|
+
: { kind: parsed.kind, token, family: 'legacy' };
|
|
45
16
|
}
|
|
46
17
|
export function getAuthTokenKind(token) {
|
|
47
18
|
return parseAuthToken(token)?.kind;
|
|
48
19
|
}
|
|
49
|
-
export function requiredTokenMessage(kind) {
|
|
50
|
-
return
|
|
20
|
+
export function requiredTokenMessage(kind, format) {
|
|
21
|
+
return `${tokenKindLabel[kind]} required (${credentialShape(kind, format)})`;
|
|
51
22
|
}
|
|
52
23
|
const allowedKindsByRequire = {
|
|
53
24
|
workspace: ['workspace'],
|
|
@@ -61,7 +32,7 @@ const allowedKindsByRequire = {
|
|
|
61
32
|
// (posts as itself), or a node token (posts as an explicit `from` agent).
|
|
62
33
|
sender: ['workspace', 'agent', 'node'],
|
|
63
34
|
};
|
|
64
|
-
export function validateTokenRequirement(tokenKind, require) {
|
|
35
|
+
export function validateTokenRequirement(tokenKind, require, format) {
|
|
65
36
|
const allowedKinds = allowedKindsByRequire[require];
|
|
66
37
|
if (allowedKinds.includes(tokenKind)) {
|
|
67
38
|
return { ok: true };
|
|
@@ -86,7 +57,7 @@ export function validateTokenRequirement(tokenKind, require) {
|
|
|
86
57
|
return {
|
|
87
58
|
ok: false,
|
|
88
59
|
code: 'unauthorized',
|
|
89
|
-
message: requiredTokenMessage(require),
|
|
60
|
+
message: requiredTokenMessage(require, format),
|
|
90
61
|
};
|
|
91
62
|
}
|
|
92
63
|
//# sourceMappingURL=tokenKind.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokenKind.js","sourceRoot":"","sources":["../../src/auth/tokenKind.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tokenKind.js","sourceRoot":"","sources":["../../src/auth/tokenKind.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AAE3F,MAAM,cAAc,GAAG;IACrB,SAAS,EAAE,eAAe;IAC1B,KAAK,EAAE,aAAa;IACpB,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,gBAAgB;CAClB,CAAC;AAaX,mDAAmD;AACnD,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3D,OAAO,MAAM,CAAC,MAAM,KAAK,IAAI;QAC3B,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE;QAC7E,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,cAAc,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAA4C,EAC5C,MAAwB;IAExB,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,cAAc,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC;AAC/E,CAAC;AAED,MAAM,qBAAqB,GAAG;IAC5B,SAAS,EAAE,CAAC,WAAW,CAAC;IACxB,KAAK,EAAE,CAAC,OAAO,CAAC;IAChB,IAAI,EAAE,CAAC,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,UAAU,CAAC;IACtB,+EAA+E;IAC/E,mDAAmD;IACnD,GAAG,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC;IAC3B,6EAA6E;IAC7E,0EAA0E;IAC1E,MAAM,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC;CAC0B,CAAC;AAMnE,MAAM,UAAU,wBAAwB,CACtC,SAAwB,EACxB,OAAoB,EACpB,MAAwB;IAExB,MAAM,YAAY,GAA6B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC9E,IAAI,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAED,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,0CAA0C;SACpD,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE,8CAA8C;SACxD,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAC9E,CAAC;IAED,OAAO;QACL,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC;KAC/C,CAAC;AACJ,CAAC"}
|
|
@@ -19,6 +19,8 @@ export declare function workspaceExpiredAuthResult(): AuthResult;
|
|
|
19
19
|
* seam: a cloud provider backed by its own identity store must not be able to
|
|
20
20
|
* admit an expired workspace. Every credential-accepting path in the engine
|
|
21
21
|
* goes through this wrapper so the check holds whatever provider is installed.
|
|
22
|
+
* The same holds for a deployment that accepts only `ar_` credentials
|
|
23
|
+
* (`restrictToArCredentials`): a legacy one is refused before the provider runs.
|
|
22
24
|
*/
|
|
23
25
|
export declare function authenticateUnexpired(auth: AuthProvider, args: {
|
|
24
26
|
token: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaceExpiry.d.ts","sourceRoot":"","sources":["../../src/auth/workspaceExpiry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"workspaceExpiry.d.ts","sourceRoot":"","sources":["../../src/auth/workspaceExpiry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIrD,kFAAkF;AAClF,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAC1D,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EACvC,GAAG,GAAE,IAAiB,GACrB,OAAO,CAGT;AAED,wBAAgB,0BAA0B,IAAI,UAAU,CAOvD;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC1D,OAAO,CAAC,UAAU,CAAC,CAQrB"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { parseCredential } from '@relaycast/types';
|
|
2
|
+
import { acceptsOnlyAr } from './credentials.js';
|
|
1
3
|
/** Error code every credential path returns for a workspace past `expires_at`. */
|
|
2
4
|
export const WORKSPACE_EXPIRED_CODE = 'workspace_expired';
|
|
3
5
|
export const WORKSPACE_EXPIRED_MESSAGE = 'Workspace has expired';
|
|
@@ -27,8 +29,13 @@ export function workspaceExpiredAuthResult() {
|
|
|
27
29
|
* seam: a cloud provider backed by its own identity store must not be able to
|
|
28
30
|
* admit an expired workspace. Every credential-accepting path in the engine
|
|
29
31
|
* goes through this wrapper so the check holds whatever provider is installed.
|
|
32
|
+
* The same holds for a deployment that accepts only `ar_` credentials
|
|
33
|
+
* (`restrictToArCredentials`): a legacy one is refused before the provider runs.
|
|
30
34
|
*/
|
|
31
35
|
export async function authenticateUnexpired(auth, args) {
|
|
36
|
+
if (acceptsOnlyAr(args.db) && parseCredential(args.token)?.family !== 'ar') {
|
|
37
|
+
return { ok: false, status: 401, code: 'unauthorized', message: 'Invalid token format' };
|
|
38
|
+
}
|
|
32
39
|
const result = await auth.authenticate(args);
|
|
33
40
|
if (!result.ok)
|
|
34
41
|
return result;
|