@noodleseed/one 0.99.1 → 0.101.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/commands/auth-ops.d.ts.map +1 -1
- package/dist/commands/auth-ops.js +6 -1
- package/dist/commands/auth-ops.js.map +1 -1
- package/dist/commands/auth-service-principals.d.ts +3 -0
- package/dist/commands/auth-service-principals.d.ts.map +1 -0
- package/dist/commands/auth-service-principals.js +380 -0
- package/dist/commands/auth-service-principals.js.map +1 -0
- package/dist/commands/author-loop.d.ts.map +1 -1
- package/dist/commands/author-loop.js +68 -0
- package/dist/commands/author-loop.js.map +1 -1
- package/dist/commands/catalog-data-auth-discovery.d.ts.map +1 -1
- package/dist/commands/catalog-data-auth-discovery.js +187 -2
- package/dist/commands/catalog-data-auth-discovery.js.map +1 -1
- package/dist/commands/catalog-data-bootstrap-authoring.js +2 -2
- package/dist/commands/catalog-data-bootstrap-authoring.js.map +1 -1
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +1 -0
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/customer-auth-smoke.d.ts +22 -0
- package/dist/commands/customer-auth-smoke.d.ts.map +1 -0
- package/dist/commands/customer-auth-smoke.js +185 -0
- package/dist/commands/customer-auth-smoke.js.map +1 -0
- package/dist/devtools-auth-session.d.ts +2 -0
- package/dist/devtools-auth-session.d.ts.map +1 -1
- package/dist/devtools-auth-session.js +13 -0
- package/dist/devtools-auth-session.js.map +1 -1
- package/dist/devtools-rpc-forwarder.js +1 -1
- package/dist/devtools-rpc-forwarder.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-auth-ref.d.ts.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-auth-ref.js +2 -0
- package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-auth-ref.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-verification-ref.d.ts.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-verification-ref.js +8 -6
- package/node_modules/@noodle-borg/agent-kit/dist/skill-verification-ref.js.map +1 -1
- package/node_modules/@noodle-borg/auth/dist/index.d.ts +1 -1
- package/node_modules/@noodle-borg/auth/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/auth/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.d.ts +5 -1
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.d.ts.map +1 -1
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.js +6 -0
- package/node_modules/@noodle-borg/auth/dist/jwt-issuer.js.map +1 -1
- package/node_modules/@noodle-borg/auth/dist/verify.d.ts +9 -2
- package/node_modules/@noodle-borg/auth/dist/verify.d.ts.map +1 -1
- package/node_modules/@noodle-borg/auth/dist/verify.js +25 -1
- package/node_modules/@noodle-borg/auth/dist/verify.js.map +1 -1
- package/node_modules/@noodle-borg/capabilities/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/capabilities/dist/index.js +7 -0
- package/node_modules/@noodle-borg/capabilities/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/module/dist/contract.d.ts +1 -1
- package/node_modules/@noodle-borg/module/dist/contract.d.ts.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/protocol/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/index.js +1 -0
- package/node_modules/@noodle-borg/protocol/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts +2 -0
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/sdk-server.js.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.d.ts +6 -0
- package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.d.ts.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.js +6 -0
- package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.js.map +1 -0
- package/node_modules/@noodle-borg/protocol/dist/tool-interaction.d.ts +1 -1
- package/node_modules/@noodle-borg/protocol/dist/tool-interaction.d.ts.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/tool-interaction.js +2 -2
- package/node_modules/@noodle-borg/protocol/dist/tool-interaction.js.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.d.ts +1 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.d.ts.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.js +2 -2
- package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.js.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/input-required.d.ts.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/input-required.js +5 -0
- package/node_modules/@noodle-borg/protocol/dist/v2/input-required.js.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/server.d.ts.map +1 -1
- package/node_modules/@noodle-borg/protocol/dist/v2/server.js +13 -9
- package/node_modules/@noodle-borg/protocol/dist/v2/server.js.map +1 -1
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +1 -1
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.d.ts +4 -0
- package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.js +4 -0
- package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/app.d.ts +2 -0
- package/node_modules/@noodle-borg/service/dist/oauth/app.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/app.js +29 -0
- package/node_modules/@noodle-borg/service/dist/oauth/app.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/metadata.d.ts +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/metadata.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/metadata.js +19 -2
- package/node_modules/@noodle-borg/service/dist/oauth/metadata.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/platform-principal-guard.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/platform-principal-guard.js +3 -1
- package/node_modules/@noodle-borg/service/dist/oauth/platform-principal-guard.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/provider.d.ts +5 -0
- package/node_modules/@noodle-borg/service/dist/oauth/provider.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/provider.js +11 -1
- package/node_modules/@noodle-borg/service/dist/oauth/provider.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.d.ts +8 -1
- package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.js +60 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.d.ts +22 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.js +199 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.d.ts +14 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.js +119 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.d.ts +16 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.js +34 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.d.ts +14 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.js +53 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.d.ts +4 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.js +98 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.d.ts +22 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.js +359 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.d.ts +165 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.js +349 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.d.ts +20 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.js +175 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.d.ts +12 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.js +20 -0
- package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.d.ts +9 -3
- package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.js +6 -0
- package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/options.d.ts +5 -0
- package/node_modules/@noodle-borg/service/dist/options.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.d.ts +24 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.js +55 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.d.ts +29 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.js +63 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.d.ts +27 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.js +33 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals.d.ts +17 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals.js +203 -0
- package/node_modules/@noodle-borg/service/dist/routes/service-principals.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/serve.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/serve.js +4 -1
- package/node_modules/@noodle-borg/service/dist/serve.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.d.ts +12 -0
- package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.js +71 -0
- package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/service.d.ts +1 -3
- package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/service.js +8 -4
- package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
- package/node_modules/@noodle-borg/service/package.json +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/handler.d.ts +5 -0
- package/node_modules/@noodle-borg/transport-http/dist/handler.d.ts.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/handler.js +4 -0
- package/node_modules/@noodle-borg/transport-http/dist/handler.js.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.d.ts +5 -0
- package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.d.ts.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.js +16 -0
- package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.js.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/index.d.ts +2 -0
- package/node_modules/@noodle-borg/transport-http/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/index.js +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/serve-request.d.ts +3 -0
- package/node_modules/@noodle-borg/transport-http/dist/serve-request.d.ts.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/serve-request.js +56 -2
- package/node_modules/@noodle-borg/transport-http/dist/serve-request.js.map +1 -1
- package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.d.ts +31 -0
- package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.d.ts.map +1 -0
- package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.js +51 -0
- package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { importJWK } from 'jose';
|
|
3
|
+
const MAX_PUBLIC_JWK_BYTES = 16 * 1024;
|
|
4
|
+
const PRIVATE_JWK_MEMBERS = ['d', 'p', 'q', 'dp', 'dq', 'qi', 'oth', 'k'];
|
|
5
|
+
/** Generate the one-time 256-bit secret returned by the management API. */
|
|
6
|
+
export function createClientSecret() {
|
|
7
|
+
return randomBytes(32).toString('base64url');
|
|
8
|
+
}
|
|
9
|
+
/** Hash a high-entropy client secret for durable storage. */
|
|
10
|
+
export function digestClientSecret(secret) {
|
|
11
|
+
return createHash('sha256').update(secret, 'utf8').digest('base64url');
|
|
12
|
+
}
|
|
13
|
+
/** Compare a presented secret with one canonical SHA-256 digest in constant time. */
|
|
14
|
+
export function secretDigestMatches(secret, expectedDigest) {
|
|
15
|
+
if (!/^[A-Za-z0-9_-]{43}$/.test(expectedDigest))
|
|
16
|
+
return false;
|
|
17
|
+
const expected = Buffer.from(expectedDigest, 'base64url');
|
|
18
|
+
const actual = Buffer.from(digestClientSecret(secret), 'base64url');
|
|
19
|
+
return (expected.length === 32 && actual.length === expected.length && timingSafeEqual(actual, expected));
|
|
20
|
+
}
|
|
21
|
+
/** Validate and import-check one public verification JWK before it reaches a store. */
|
|
22
|
+
export async function validatePublicJwk(value, algorithm) {
|
|
23
|
+
if (algorithm !== 'RS256' && algorithm !== 'ES256') {
|
|
24
|
+
throw new Error('service-principal JWK algorithm must be RS256 or ES256');
|
|
25
|
+
}
|
|
26
|
+
if (!isRecord(value))
|
|
27
|
+
throw new Error('service-principal public JWK must be an object');
|
|
28
|
+
const serialized = serializeJwk(value);
|
|
29
|
+
if (Buffer.byteLength(serialized, 'utf8') > MAX_PUBLIC_JWK_BYTES) {
|
|
30
|
+
throw new Error('service-principal public JWK must be at most 16 KiB');
|
|
31
|
+
}
|
|
32
|
+
for (const member of PRIVATE_JWK_MEMBERS) {
|
|
33
|
+
if (Object.hasOwn(value, member)) {
|
|
34
|
+
throw new Error(`service-principal public JWK must not contain private member ${member}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
validateCommonJwkMetadata(value, algorithm);
|
|
38
|
+
if (algorithm === 'RS256')
|
|
39
|
+
validateRsaJwk(value);
|
|
40
|
+
else
|
|
41
|
+
validateEcJwk(value);
|
|
42
|
+
try {
|
|
43
|
+
await importJWK(value, algorithm);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error(`service-principal ${algorithm} public JWK is malformed`);
|
|
47
|
+
}
|
|
48
|
+
return Object.freeze({
|
|
49
|
+
algorithm,
|
|
50
|
+
publicJwk: Object.freeze(structuredClone(value)),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function serializeJwk(value) {
|
|
54
|
+
try {
|
|
55
|
+
return JSON.stringify(value);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new Error('service-principal public JWK must be JSON serializable');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function validateCommonJwkMetadata(jwk, algorithm) {
|
|
62
|
+
if (jwk.alg !== undefined && jwk.alg !== algorithm) {
|
|
63
|
+
throw new Error('service-principal JWK declared algorithm does not match its pinned algorithm');
|
|
64
|
+
}
|
|
65
|
+
if (jwk.use !== undefined && jwk.use !== 'sig') {
|
|
66
|
+
throw new Error('service-principal JWK use must be sig');
|
|
67
|
+
}
|
|
68
|
+
if (jwk.key_ops !== undefined &&
|
|
69
|
+
(!Array.isArray(jwk.key_ops) || jwk.key_ops.length !== 1 || jwk.key_ops[0] !== 'verify')) {
|
|
70
|
+
throw new Error('service-principal JWK key_ops must contain only verify');
|
|
71
|
+
}
|
|
72
|
+
if (jwk.kid !== undefined &&
|
|
73
|
+
(typeof jwk.kid !== 'string' || jwk.kid.length === 0 || jwk.kid.length > 200)) {
|
|
74
|
+
throw new Error('service-principal JWK kid must be between 1 and 200 characters');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function validateRsaJwk(jwk) {
|
|
78
|
+
if (jwk.kty !== 'RSA' || typeof jwk.n !== 'string' || typeof jwk.e !== 'string') {
|
|
79
|
+
throw new Error('RS256 requires an RSA public JWK');
|
|
80
|
+
}
|
|
81
|
+
const modulus = decodeCanonicalBase64url(jwk.n, 'RSA modulus');
|
|
82
|
+
const bits = modulusBitLength(modulus);
|
|
83
|
+
if (bits < 2048 || bits > 4096) {
|
|
84
|
+
throw new Error('RS256 RSA modulus must be between 2048 and 4096 bits');
|
|
85
|
+
}
|
|
86
|
+
decodeCanonicalBase64url(jwk.e, 'RSA exponent');
|
|
87
|
+
}
|
|
88
|
+
function validateEcJwk(jwk) {
|
|
89
|
+
if (jwk.kty !== 'EC' ||
|
|
90
|
+
jwk.crv !== 'P-256' ||
|
|
91
|
+
typeof jwk.x !== 'string' ||
|
|
92
|
+
typeof jwk.y !== 'string') {
|
|
93
|
+
throw new Error('ES256 requires a P-256 EC public JWK');
|
|
94
|
+
}
|
|
95
|
+
if (decodeCanonicalBase64url(jwk.x, 'EC x coordinate').length !== 32 ||
|
|
96
|
+
decodeCanonicalBase64url(jwk.y, 'EC y coordinate').length !== 32) {
|
|
97
|
+
throw new Error('ES256 requires 256-bit EC coordinates');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function decodeCanonicalBase64url(value, label) {
|
|
101
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value))
|
|
102
|
+
throw new Error(`${label} must be base64url`);
|
|
103
|
+
const decoded = Buffer.from(value, 'base64url');
|
|
104
|
+
if (decoded.length === 0 || decoded.toString('base64url') !== value) {
|
|
105
|
+
throw new Error(`${label} must be canonical base64url`);
|
|
106
|
+
}
|
|
107
|
+
return decoded;
|
|
108
|
+
}
|
|
109
|
+
function modulusBitLength(value) {
|
|
110
|
+
const firstNonZero = value.findIndex((byte) => byte !== 0);
|
|
111
|
+
if (firstNonZero === -1)
|
|
112
|
+
return 0;
|
|
113
|
+
const first = value[firstNonZero];
|
|
114
|
+
return (value.length - firstNonZero - 1) * 8 + (32 - Math.clz32(first));
|
|
115
|
+
}
|
|
116
|
+
function isRecord(value) {
|
|
117
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=service-principal-credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-credentials.js","sourceRoot":"","sources":["../../src/oauth/service-principal-credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TokenVerifier, VerifiedTokenEnvelope } from '@noodle-borg/auth';
|
|
2
|
+
import type { OwnerTokenVerification, OwnerTokenVerifier } from '@noodle-borg/module';
|
|
3
|
+
import type { ServicePrincipalStore } from './service-principal-store.js';
|
|
4
|
+
export interface ResolvedServicePrincipalTarget {
|
|
5
|
+
readonly org: string;
|
|
6
|
+
readonly app: string;
|
|
7
|
+
readonly environment: string;
|
|
8
|
+
}
|
|
9
|
+
type ServiceCapableTokenVerifier = (token: string, resource: string) => Promise<VerifiedTokenEnvelope | OwnerTokenVerification | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Revalidate the private principal/grant/credential binding for every machine-authenticated data-plane
|
|
12
|
+
* request. The private binding is consumed here and never projected into the protocol caller context.
|
|
13
|
+
*/
|
|
14
|
+
export declare function guardServicePrincipalAccessTokenVerifier(verifier: TokenVerifier | ServiceCapableTokenVerifier, store: ServicePrincipalStore | undefined, resolveResource: (resource: string) => Promise<ResolvedServicePrincipalTarget | undefined>, now?: () => number): OwnerTokenVerifier;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=service-principal-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-guard.d.ts","sourceRoot":"","sources":["../../src/oauth/service-principal-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,KAAK,2BAA2B,GAAG,CACjC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,qBAAqB,GAAG,sBAAsB,GAAG,IAAI,CAAC,CAAC;AAEpE;;;GAGG;AACH,wBAAgB,wCAAwC,CACtD,QAAQ,EAAE,aAAa,GAAG,2BAA2B,EACrD,KAAK,EAAE,qBAAqB,GAAG,SAAS,EACxC,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,8BAA8B,GAAG,SAAS,CAAC,EAC1F,GAAG,GAAE,MAAM,MAAiB,GAC3B,kBAAkB,CAyBpB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revalidate the private principal/grant/credential binding for every machine-authenticated data-plane
|
|
3
|
+
* request. The private binding is consumed here and never projected into the protocol caller context.
|
|
4
|
+
*/
|
|
5
|
+
export function guardServicePrincipalAccessTokenVerifier(verifier, store, resolveResource, now = Date.now) {
|
|
6
|
+
return async (token, resource) => {
|
|
7
|
+
const verification = await verifier(token, resource);
|
|
8
|
+
if (verification === null || verification.caller.identityKind !== 'service') {
|
|
9
|
+
return verification;
|
|
10
|
+
}
|
|
11
|
+
const binding = 'servicePrincipal' in verification ? verification.servicePrincipal : undefined;
|
|
12
|
+
if (binding === undefined || store === undefined)
|
|
13
|
+
return null;
|
|
14
|
+
try {
|
|
15
|
+
const target = await resolveResource(resource);
|
|
16
|
+
if (target === undefined)
|
|
17
|
+
return null;
|
|
18
|
+
const valid = await store.validateAccessBinding({
|
|
19
|
+
principalId: verification.caller.subject,
|
|
20
|
+
grantId: binding.grantId,
|
|
21
|
+
credentialId: binding.credentialId,
|
|
22
|
+
org: target.org,
|
|
23
|
+
app: target.app,
|
|
24
|
+
environment: target.environment,
|
|
25
|
+
now: now(),
|
|
26
|
+
});
|
|
27
|
+
return valid ? { caller: verification.caller } : null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=service-principal-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-guard.js","sourceRoot":"","sources":["../../src/oauth/service-principal-guard.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,MAAM,UAAU,wCAAwC,CACtD,QAAqD,EACrD,KAAwC,EACxC,eAA0F,EAC1F,MAAoB,IAAI,CAAC,GAAG;IAE5B,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC/B,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YAC5E,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,MAAM,OAAO,GAAG,kBAAkB,IAAI,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/F,IAAI,OAAO,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAC9D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;YAC/C,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAC;YACtC,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,qBAAqB,CAAC;gBAC9C,WAAW,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO;gBACxC,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,GAAG,EAAE,GAAG,EAAE;aACX,CAAC,CAAC;YACH,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type TenantRouteRef } from '@noodle-borg/module';
|
|
2
|
+
import type { ServerRegistry } from '../registry.js';
|
|
3
|
+
export interface ServicePrincipalResourceRouting {
|
|
4
|
+
readonly legacyOrigin: string;
|
|
5
|
+
readonly allowedBaseDomains: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
export interface ResolvedServicePrincipalResource {
|
|
8
|
+
readonly resource: string;
|
|
9
|
+
readonly tenant: TenantRouteRef;
|
|
10
|
+
readonly deploymentId?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Resolve only a byte-exact canonical MCP resource that is actively served right now. */
|
|
13
|
+
export declare function resolveServicePrincipalResource(resource: string, registry: ServerRegistry, routing: ServicePrincipalResourceRouting): Promise<ResolvedServicePrincipalResource | undefined>;
|
|
14
|
+
//# sourceMappingURL=service-principal-resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-resource.d.ts","sourceRoot":"","sources":["../../src/oauth/service-principal-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,0FAA0F;AAC1F,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,gCAAgC,GAAG,SAAS,CAAC,CAavD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { formatTenantMcpUrl, parseLegacyTenantMcpPath, parsePublicTenantMcpUrl, } from '@noodle-borg/module';
|
|
2
|
+
import { tenantMcpUrl } from '../registry-helpers.js';
|
|
3
|
+
/** Resolve only a byte-exact canonical MCP resource that is actively served right now. */
|
|
4
|
+
export async function resolveServicePrincipalResource(resource, registry, routing) {
|
|
5
|
+
const tenant = exactTenant(resource, routing);
|
|
6
|
+
if (tenant === undefined)
|
|
7
|
+
return undefined;
|
|
8
|
+
const target = tenant.serverVersion === undefined
|
|
9
|
+
? await registry.getActiveByTenant(tenant)
|
|
10
|
+
: await registry.getActiveByTenantVersion(tenant, tenant.serverVersion);
|
|
11
|
+
if (target === undefined)
|
|
12
|
+
return undefined;
|
|
13
|
+
return {
|
|
14
|
+
resource,
|
|
15
|
+
tenant,
|
|
16
|
+
...(target.deploymentId === undefined ? {} : { deploymentId: target.deploymentId }),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function exactTenant(resource, routing) {
|
|
20
|
+
let url;
|
|
21
|
+
try {
|
|
22
|
+
url = new URL(resource);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
if (url.search !== '' || url.hash !== '')
|
|
28
|
+
return undefined;
|
|
29
|
+
const publicTenant = parsePublicTenantMcpUrl(resource, routing.allowedBaseDomains);
|
|
30
|
+
if (publicTenant !== undefined) {
|
|
31
|
+
const exact = routing.allowedBaseDomains.some((baseDomain) => formatTenantMcpUrl(baseDomain, publicTenant) === resource);
|
|
32
|
+
return exact ? publicTenant : undefined;
|
|
33
|
+
}
|
|
34
|
+
let legacyOrigin;
|
|
35
|
+
try {
|
|
36
|
+
legacyOrigin = new URL(routing.legacyOrigin);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
if (legacyOrigin.pathname !== '/' ||
|
|
42
|
+
legacyOrigin.search !== '' ||
|
|
43
|
+
legacyOrigin.hash !== '' ||
|
|
44
|
+
url.origin !== legacyOrigin.origin) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const legacyTenant = parseLegacyTenantMcpPath(url.pathname);
|
|
48
|
+
if (legacyTenant === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
const canonical = tenantMcpUrl(legacyOrigin.origin, legacyTenant, legacyTenant.serverVersion);
|
|
51
|
+
return canonical === resource ? legacyTenant : undefined;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=service-principal-resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-resource.js","sourceRoot":"","sources":["../../src/oauth/service-principal-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,GAExB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAatD,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,QAAgB,EAChB,QAAwB,EACxB,OAAwC;IAExC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,MAAM,GACV,MAAM,CAAC,aAAa,KAAK,SAAS;QAChC,CAAC,CAAC,MAAM,QAAQ,CAAC,iBAAiB,CAAC,MAAM,CAAC;QAC1C,CAAC,CAAC,MAAM,QAAQ,CAAC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IAC5E,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,OAAO;QACL,QAAQ;QACR,MAAM;QACN,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;KACpF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,QAAgB,EAChB,OAAwC;IAExC,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAE3D,MAAM,YAAY,GAAG,uBAAuB,CAAC,QAAQ,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACnF,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAC3C,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE,YAAY,CAAC,KAAK,QAAQ,CAC1E,CAAC;QACF,OAAO,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1C,CAAC;IAED,IAAI,YAAiB,CAAC;IACtB,IAAI,CAAC;QACH,YAAY,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IACE,YAAY,CAAC,QAAQ,KAAK,GAAG;QAC7B,YAAY,CAAC,MAAM,KAAK,EAAE;QAC1B,YAAY,CAAC,IAAI,KAAK,EAAE;QACxB,GAAG,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,EAClC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,YAAY,GAAG,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5D,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACjD,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,aAAa,CAAC,CAAC;IAC9F,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC"}
|
package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Pool } from 'pg';
|
|
2
|
+
/** Additively installs the durable service-principal and assertion-replay tables. */
|
|
3
|
+
export declare function ensureServicePrincipalSchema(pool: Pool): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=service-principal-store-postgres-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-store-postgres-schema.d.ts","sourceRoot":"","sources":["../../src/oauth/service-principal-store-postgres-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B,qFAAqF;AACrF,wBAAsB,4BAA4B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA+F5E"}
|
package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Additively installs the durable service-principal and assertion-replay tables. */
|
|
2
|
+
export async function ensureServicePrincipalSchema(pool) {
|
|
3
|
+
await pool.query(`
|
|
4
|
+
CREATE TABLE IF NOT EXISTS oauth_service_principals (
|
|
5
|
+
principal_id text PRIMARY KEY
|
|
6
|
+
CHECK (principal_id ~ '^spn_[0-9a-f-]{36}$'),
|
|
7
|
+
org_slug text NOT NULL,
|
|
8
|
+
name text NOT NULL CHECK (char_length(name) BETWEEN 1 AND 80),
|
|
9
|
+
status text NOT NULL CHECK (status IN ('active', 'revoked')),
|
|
10
|
+
created_by_subject text NOT NULL,
|
|
11
|
+
created_at timestamptz NOT NULL,
|
|
12
|
+
updated_at timestamptz NOT NULL,
|
|
13
|
+
revoked_at timestamptz,
|
|
14
|
+
revoked_by_subject text,
|
|
15
|
+
UNIQUE (principal_id, org_slug)
|
|
16
|
+
)
|
|
17
|
+
`);
|
|
18
|
+
await pool.query(`
|
|
19
|
+
CREATE TABLE IF NOT EXISTS oauth_service_principal_grants (
|
|
20
|
+
grant_id text PRIMARY KEY
|
|
21
|
+
CHECK (grant_id ~ '^spg_[0-9a-f-]{36}$'),
|
|
22
|
+
principal_id text NOT NULL,
|
|
23
|
+
org_slug text NOT NULL,
|
|
24
|
+
app_slug text NOT NULL,
|
|
25
|
+
environment text NOT NULL,
|
|
26
|
+
scopes text[] NOT NULL CHECK (cardinality(scopes) <= 64),
|
|
27
|
+
status text NOT NULL CHECK (status IN ('active', 'revoked')),
|
|
28
|
+
created_by_subject text NOT NULL,
|
|
29
|
+
created_at timestamptz NOT NULL,
|
|
30
|
+
updated_at timestamptz NOT NULL,
|
|
31
|
+
revoked_at timestamptz,
|
|
32
|
+
revoked_by_subject text,
|
|
33
|
+
FOREIGN KEY (principal_id, org_slug)
|
|
34
|
+
REFERENCES oauth_service_principals (principal_id, org_slug)
|
|
35
|
+
ON DELETE RESTRICT
|
|
36
|
+
)
|
|
37
|
+
`);
|
|
38
|
+
await pool.query(`
|
|
39
|
+
CREATE UNIQUE INDEX IF NOT EXISTS oauth_service_principal_active_grant_target_uq
|
|
40
|
+
ON oauth_service_principal_grants (principal_id, app_slug, environment)
|
|
41
|
+
WHERE status = 'active'
|
|
42
|
+
`);
|
|
43
|
+
await pool.query(`
|
|
44
|
+
CREATE INDEX IF NOT EXISTS oauth_service_principal_grants_lookup_idx
|
|
45
|
+
ON oauth_service_principal_grants (principal_id, status)
|
|
46
|
+
`);
|
|
47
|
+
await pool.query(`
|
|
48
|
+
CREATE TABLE IF NOT EXISTS oauth_service_principal_credentials (
|
|
49
|
+
credential_id text PRIMARY KEY
|
|
50
|
+
CHECK (credential_id ~ '^spc_[0-9a-f-]{36}$'),
|
|
51
|
+
principal_id text NOT NULL,
|
|
52
|
+
org_slug text NOT NULL,
|
|
53
|
+
kind text NOT NULL CHECK (kind IN ('public_jwk', 'client_secret')),
|
|
54
|
+
label text NOT NULL CHECK (char_length(label) BETWEEN 1 AND 80),
|
|
55
|
+
algorithm text CHECK (algorithm IN ('RS256', 'ES256')),
|
|
56
|
+
kid text CHECK (kid IS NULL OR char_length(kid) BETWEEN 1 AND 200),
|
|
57
|
+
public_jwk jsonb,
|
|
58
|
+
secret_digest text,
|
|
59
|
+
status text NOT NULL CHECK (status IN ('active', 'revoked')),
|
|
60
|
+
created_by_subject text NOT NULL,
|
|
61
|
+
created_at timestamptz NOT NULL,
|
|
62
|
+
updated_at timestamptz NOT NULL,
|
|
63
|
+
expires_at timestamptz,
|
|
64
|
+
revoked_at timestamptz,
|
|
65
|
+
revoked_by_subject text,
|
|
66
|
+
FOREIGN KEY (principal_id, org_slug)
|
|
67
|
+
REFERENCES oauth_service_principals (principal_id, org_slug)
|
|
68
|
+
ON DELETE RESTRICT,
|
|
69
|
+
CHECK (
|
|
70
|
+
(kind = 'public_jwk' AND algorithm IS NOT NULL AND public_jwk IS NOT NULL
|
|
71
|
+
AND secret_digest IS NULL)
|
|
72
|
+
OR
|
|
73
|
+
(kind = 'client_secret' AND algorithm IS NULL AND kid IS NULL
|
|
74
|
+
AND public_jwk IS NULL AND secret_digest IS NOT NULL)
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
`);
|
|
78
|
+
await pool.query(`
|
|
79
|
+
CREATE INDEX IF NOT EXISTS oauth_service_principal_active_credentials_idx
|
|
80
|
+
ON oauth_service_principal_credentials (principal_id, kind, expires_at)
|
|
81
|
+
WHERE status = 'active'
|
|
82
|
+
`);
|
|
83
|
+
await pool.query(`
|
|
84
|
+
CREATE TABLE IF NOT EXISTS oauth_client_assertion_nonces (
|
|
85
|
+
credential_id text NOT NULL
|
|
86
|
+
REFERENCES oauth_service_principal_credentials (credential_id) ON DELETE CASCADE,
|
|
87
|
+
jti text NOT NULL CHECK (char_length(jti) BETWEEN 1 AND 200),
|
|
88
|
+
expires_at timestamptz NOT NULL,
|
|
89
|
+
created_at timestamptz NOT NULL,
|
|
90
|
+
PRIMARY KEY (credential_id, jti)
|
|
91
|
+
)
|
|
92
|
+
`);
|
|
93
|
+
await pool.query(`
|
|
94
|
+
CREATE INDEX IF NOT EXISTS oauth_client_assertion_nonces_expiry_idx
|
|
95
|
+
ON oauth_client_assertion_nonces (expires_at)
|
|
96
|
+
`);
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=service-principal-store-postgres-schema.js.map
|
package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-store-postgres-schema.js","sourceRoot":"","sources":["../../src/oauth/service-principal-store-postgres-schema.ts"],"names":[],"mappings":"AAEA,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,IAAU;IAC3D,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;GAchB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;GAmBhB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;GAIhB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,KAAK,CAAC;;;GAGhB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BhB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;GAIhB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;GAShB,CAAC,CAAC;IACH,MAAM,IAAI,CAAC,KAAK,CAAC;;;GAGhB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Pool } from 'pg';
|
|
2
|
+
import { type ActiveServicePrincipalClient, type AssertionJtiInput, type CreateServicePrincipalGrantInput, type CreateServicePrincipalInput, type CreateStoredCredentialInput, type CredentialMutation, type GrantMutation, type PrincipalMutation, type PrincipalRef, type ServicePrincipalAccessBinding, type ServicePrincipalCredentialRecord, type ServicePrincipalGrantRecord, type ServicePrincipalRecord, type ServicePrincipalStore, type ServicePrincipalView } from './service-principal-store.js';
|
|
3
|
+
/** Durable, organization-isolated service-principal lifecycle and assertion replay store. */
|
|
4
|
+
export declare class PostgresServicePrincipalStore implements ServicePrincipalStore {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(pool: Pool, options?: {
|
|
7
|
+
readonly now?: () => Date;
|
|
8
|
+
});
|
|
9
|
+
ensureSchema(): Promise<void>;
|
|
10
|
+
createPrincipal(input: CreateServicePrincipalInput): Promise<ServicePrincipalRecord>;
|
|
11
|
+
listPrincipals(org: string): Promise<readonly ServicePrincipalRecord[]>;
|
|
12
|
+
getPrincipal(input: PrincipalRef): Promise<ServicePrincipalView | undefined>;
|
|
13
|
+
revokePrincipal(input: PrincipalMutation): Promise<boolean>;
|
|
14
|
+
createGrant(input: CreateServicePrincipalGrantInput): Promise<ServicePrincipalGrantRecord>;
|
|
15
|
+
revokeGrant(input: GrantMutation): Promise<boolean>;
|
|
16
|
+
createCredential(input: CreateStoredCredentialInput): Promise<ServicePrincipalCredentialRecord>;
|
|
17
|
+
revokeCredential(input: CredentialMutation): Promise<boolean>;
|
|
18
|
+
loadActiveClient(clientId: string, now: number): Promise<ActiveServicePrincipalClient | undefined>;
|
|
19
|
+
validateAccessBinding(input: ServicePrincipalAccessBinding): Promise<boolean>;
|
|
20
|
+
consumeAssertionJti(input: AssertionJtiInput): Promise<boolean>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=service-principal-store-postgres.d.ts.map
|
package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-principal-store-postgres.d.ts","sourceRoot":"","sources":["../../src/oauth/service-principal-store-postgres.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,IAAI,CAAC;AAG3C,OAAO,EACL,KAAK,4BAA4B,EAEjC,KAAK,iBAAiB,EACtB,KAAK,gCAAgC,EACrC,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EAEvB,KAAK,aAAa,EAGlB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAEjB,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EACrC,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAK1B,MAAM,8BAA8B,CAAC;AAgDtC,6FAA6F;AAC7F,qBAAa,6BAA8B,YAAW,qBAAqB;;gBAI7D,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;KAAO;IAK7D,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,eAAe,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAkBpF,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,sBAAsB,EAAE,CAAC;IAUvE,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IA4B5E,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB3D,WAAW,CAAC,KAAK,EAAE,gCAAgC,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAyC1F,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBnD,gBAAgB,CACpB,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,gCAAgC,CAAC;IA0DtC,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB7D,gBAAgB,CACpB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,4BAA4B,GAAG,SAAS,CAAC;IA0C9C,qBAAqB,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,OAAO,CAAC;IA0B7E,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;CAqCtE"}
|