@hilbras/keystone 2.5.0 ā 3.0.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 +423 -0
- package/README.md +85 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -11
- package/dist/index.js.map +1 -1
- package/dist/plugins/auth.d.ts +2 -0
- package/dist/plugins/auth.d.ts.map +1 -1
- package/dist/plugins/auth.js +21 -7
- package/dist/plugins/auth.js.map +1 -1
- package/dist/plugins/machinePrincipal.d.ts +28 -0
- package/dist/plugins/machinePrincipal.d.ts.map +1 -0
- package/dist/plugins/machinePrincipal.js +45 -0
- package/dist/plugins/machinePrincipal.js.map +1 -0
- package/dist/plugins/rateLimit.d.ts +10 -7
- package/dist/plugins/rateLimit.d.ts.map +1 -1
- package/dist/plugins/rateLimit.js +75 -36
- package/dist/plugins/rateLimit.js.map +1 -1
- package/dist/routes/admin/organizations.d.ts.map +1 -1
- package/dist/routes/admin/organizations.js +2 -0
- package/dist/routes/admin/organizations.js.map +1 -1
- package/dist/routes/admin/platform.d.ts.map +1 -1
- package/dist/routes/admin/platform.js +14 -1
- package/dist/routes/admin/platform.js.map +1 -1
- package/dist/routes/apiKeys.d.ts.map +1 -1
- package/dist/routes/apiKeys.js +37 -5
- package/dist/routes/apiKeys.js.map +1 -1
- package/dist/routes/auth.d.ts.map +1 -1
- package/dist/routes/auth.js +104 -3
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/emailVerification.d.ts.map +1 -1
- package/dist/routes/emailVerification.js +2 -0
- package/dist/routes/emailVerification.js.map +1 -1
- package/dist/routes/federation.d.ts.map +1 -1
- package/dist/routes/federation.js +8 -2
- package/dist/routes/federation.js.map +1 -1
- package/dist/routes/magicLinks.d.ts.map +1 -1
- package/dist/routes/magicLinks.js +2 -0
- package/dist/routes/magicLinks.js.map +1 -1
- package/dist/routes/oauth2.d.ts.map +1 -1
- package/dist/routes/oauth2.js +24 -4
- package/dist/routes/oauth2.js.map +1 -1
- package/dist/routes/password.d.ts.map +1 -1
- package/dist/routes/password.js +2 -0
- package/dist/routes/password.js.map +1 -1
- package/dist/routes/profile.js +2 -2
- package/dist/routes/profile.js.map +1 -1
- package/dist/routes/scim.d.ts.map +1 -1
- package/dist/routes/scim.js +2 -0
- package/dist/routes/scim.js.map +1 -1
- package/dist/routes/serviceAccounts.d.ts.map +1 -1
- package/dist/routes/serviceAccounts.js +17 -1
- package/dist/routes/serviceAccounts.js.map +1 -1
- package/dist/routes/sessions.js +3 -3
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/smsOtp.d.ts.map +1 -1
- package/dist/routes/smsOtp.js +10 -0
- package/dist/routes/smsOtp.js.map +1 -1
- package/dist/routes/totp.d.ts.map +1 -1
- package/dist/routes/totp.js +38 -6
- package/dist/routes/totp.js.map +1 -1
- package/dist/routes/webauthn.d.ts.map +1 -1
- package/dist/routes/webauthn.js +8 -2
- package/dist/routes/webauthn.js.map +1 -1
- package/dist/services/configuration/profiles.d.ts +26 -0
- package/dist/services/configuration/profiles.d.ts.map +1 -1
- package/dist/services/configuration/profiles.js +80 -1
- package/dist/services/configuration/profiles.js.map +1 -1
- package/dist/services/events/subscribers/auditLog.d.ts.map +1 -1
- package/dist/services/events/subscribers/auditLog.js +38 -3
- package/dist/services/events/subscribers/auditLog.js.map +1 -1
- package/dist/services/events/types.d.ts +3 -1
- package/dist/services/events/types.d.ts.map +1 -1
- package/dist/services/events/validate.d.ts +1 -0
- package/dist/services/events/validate.d.ts.map +1 -1
- package/dist/services/events/validate.js +5 -1
- package/dist/services/events/validate.js.map +1 -1
- package/dist/services/localRateLimit.d.ts +44 -0
- package/dist/services/localRateLimit.d.ts.map +1 -0
- package/dist/services/localRateLimit.js +86 -0
- package/dist/services/localRateLimit.js.map +1 -0
- package/dist/services/refreshTokenState.d.ts +5 -0
- package/dist/services/refreshTokenState.d.ts.map +1 -0
- package/dist/services/refreshTokenState.js +30 -0
- package/dist/services/refreshTokenState.js.map +1 -0
- package/dist/services/scopes.d.ts +113 -0
- package/dist/services/scopes.d.ts.map +1 -0
- package/dist/services/scopes.js +138 -0
- package/dist/services/scopes.js.map +1 -0
- package/dist/services/setup/token.d.ts +12 -0
- package/dist/services/setup/token.d.ts.map +1 -1
- package/dist/services/setup/token.js +27 -3
- package/dist/services/setup/token.js.map +1 -1
- package/dist/services/tokens.d.ts +1 -0
- package/dist/services/tokens.d.ts.map +1 -1
- package/dist/services/tokens.js +1 -1
- package/dist/services/tokens.js.map +1 -1
- package/dist/services/trustedProxies.d.ts +24 -0
- package/dist/services/trustedProxies.d.ts.map +1 -1
- package/dist/services/trustedProxies.js +19 -0
- package/dist/services/trustedProxies.js.map +1 -1
- package/dist/services/webhooks.d.ts +16 -0
- package/dist/services/webhooks.d.ts.map +1 -1
- package/dist/services/webhooks.js +48 -3
- package/dist/services/webhooks.js.map +1 -1
- package/dist/setup-server.js +47 -3
- package/dist/setup-server.js.map +1 -1
- package/docs/API-REVIEW.md +121 -0
- package/docs/API.md +457 -0
- package/docs/ARCHITECTURE.md +142 -0
- package/docs/CONTRIBUTING.md +61 -0
- package/docs/DEPLOYMENT.md +257 -0
- package/docs/INTEGRATION.md +336 -0
- package/docs/LOGIN_FORM_INTEGRATION.md +306 -0
- package/docs/MIGRATION-1.7.md +70 -0
- package/docs/MIGRATION-1.8.md +183 -0
- package/docs/MIGRATION-1.9.md +200 -0
- package/docs/MIGRATION-2.0.md +203 -0
- package/docs/MIGRATION-2.4.md +185 -0
- package/docs/PERFORMANCE.md +155 -0
- package/docs/RBAC.md +100 -0
- package/docs/RE-AUDIT.md +72 -0
- package/docs/README.md +54 -0
- package/docs/RELEASE-1.7.md +53 -0
- package/docs/ROADMAP.md +41 -0
- package/docs/SECURITY.md +143 -0
- package/docs/adrs/001-identity-connectors-as-adapters.md +27 -0
- package/docs/adrs/002-versioned-event-bus.md +30 -0
- package/docs/adrs/003-bullmq-for-background-work.md +20 -0
- package/docs/adrs/004-argon2id-password-hashing.md +19 -0
- package/docs/plans/KEYSTONE_IMPROVEMENT_PLAN.md +334 -0
- package/docs/plans/UI_SIMPLIFICATION_IMPROVEMENT_PLAN.md +271 -0
- package/docs/security/audit.md +82 -0
- package/docs/security/configuration.md +60 -0
- package/docs/security/enterprise-sso.md +193 -0
- package/docs/security/mtls.md +132 -0
- package/docs/security/proxy-security.md +128 -0
- package/docs/security/rate-limiting.md +79 -0
- package/docs/security/registry-exceptions.md +34 -0
- package/docs/security/registry.json +649 -0
- package/docs/security/registry.md +657 -0
- package/docs/security/scopes.md +45 -0
- package/docs/security/supply-chain.md +49 -0
- package/docs/security/trust-boundaries.md +111 -0
- package/package.json +15 -6
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process rate limiting, for when Redis is unavailable.
|
|
3
|
+
*
|
|
4
|
+
* The distributed limiter is the real control: it is shared across instances, so
|
|
5
|
+
* a client cannot multiply its budget by spreading requests over a fleet. But it
|
|
6
|
+
* depends on Redis, and when Redis is down the previous behaviour was to allow
|
|
7
|
+
* everything.
|
|
8
|
+
*
|
|
9
|
+
* That is backwards. An outage is exactly when an attacker wants unlimited
|
|
10
|
+
* attempts at `login`, `mfa-verify`, or a token exchange ā the requests that
|
|
11
|
+
* matter are the ones worth brute-forcing. Losing the limiter because a cache
|
|
12
|
+
* restarted removes the control at the worst possible moment.
|
|
13
|
+
*
|
|
14
|
+
* So sensitive endpoints carry a local fallback. It is strictly weaker than the
|
|
15
|
+
* distributed limiter: a client gets `instanceCount` times the budget by
|
|
16
|
+
* spreading requests, since each process counts independently. That is a
|
|
17
|
+
* degradation worth having, and unbounded is not.
|
|
18
|
+
*
|
|
19
|
+
* The store is bounded. An unbounded map keyed by client address is itself a
|
|
20
|
+
* denial-of-service vector ā an attacker rotating addresses would grow it without
|
|
21
|
+
* limit ā so expired windows are swept and the oldest entries are evicted once
|
|
22
|
+
* the cap is reached.
|
|
23
|
+
*/
|
|
24
|
+
export type LocalLimiterResult = {
|
|
25
|
+
allowed: true;
|
|
26
|
+
} | {
|
|
27
|
+
allowed: false;
|
|
28
|
+
retryAfterSeconds: number;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Count one request against an in-process window.
|
|
32
|
+
*
|
|
33
|
+
* Fixed window rather than sliding: a sliding window needs per-request
|
|
34
|
+
* timestamps and this is a degraded path, not the primary control. The
|
|
35
|
+
* consequence is that a client can spend its budget at the end of one window and
|
|
36
|
+
* again at the start of the next, which is acceptable for a fallback and would
|
|
37
|
+
* not be for the primary limiter.
|
|
38
|
+
*/
|
|
39
|
+
export declare function localRateLimit(key: string, maxAttempts: number, windowSeconds: number): LocalLimiterResult;
|
|
40
|
+
/** Test seam: forget every tracked window. */
|
|
41
|
+
export declare function resetLocalRateLimits(): void;
|
|
42
|
+
/** Test seam: how many windows are currently tracked. */
|
|
43
|
+
export declare function localRateLimitSize(): number;
|
|
44
|
+
//# sourceMappingURL=localRateLimit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localRateLimit.d.ts","sourceRoot":"","sources":["../../src/services/localRateLimit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAoCH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,kBAAkB,CAkBpB;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process rate limiting, for when Redis is unavailable.
|
|
3
|
+
*
|
|
4
|
+
* The distributed limiter is the real control: it is shared across instances, so
|
|
5
|
+
* a client cannot multiply its budget by spreading requests over a fleet. But it
|
|
6
|
+
* depends on Redis, and when Redis is down the previous behaviour was to allow
|
|
7
|
+
* everything.
|
|
8
|
+
*
|
|
9
|
+
* That is backwards. An outage is exactly when an attacker wants unlimited
|
|
10
|
+
* attempts at `login`, `mfa-verify`, or a token exchange ā the requests that
|
|
11
|
+
* matter are the ones worth brute-forcing. Losing the limiter because a cache
|
|
12
|
+
* restarted removes the control at the worst possible moment.
|
|
13
|
+
*
|
|
14
|
+
* So sensitive endpoints carry a local fallback. It is strictly weaker than the
|
|
15
|
+
* distributed limiter: a client gets `instanceCount` times the budget by
|
|
16
|
+
* spreading requests, since each process counts independently. That is a
|
|
17
|
+
* degradation worth having, and unbounded is not.
|
|
18
|
+
*
|
|
19
|
+
* The store is bounded. An unbounded map keyed by client address is itself a
|
|
20
|
+
* denial-of-service vector ā an attacker rotating addresses would grow it without
|
|
21
|
+
* limit ā so expired windows are swept and the oldest entries are evicted once
|
|
22
|
+
* the cap is reached.
|
|
23
|
+
*/
|
|
24
|
+
/** Cap on tracked keys. Roughly a few thousand clients per process. */
|
|
25
|
+
const MAX_TRACKED_KEYS = 10_000;
|
|
26
|
+
const windows = new Map();
|
|
27
|
+
/** Drop expired windows. Cheap enough to run on every check at this size. */
|
|
28
|
+
function sweep(now) {
|
|
29
|
+
for (const [key, window] of windows) {
|
|
30
|
+
if (window.resetAt <= now)
|
|
31
|
+
windows.delete(key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Evict the oldest window when the cap is reached.
|
|
36
|
+
*
|
|
37
|
+
* `Map` preserves insertion order, so the first key is the oldest. Its window is
|
|
38
|
+
* expired, so evicting it grants no extra budget ā it simply forgets a key that
|
|
39
|
+
* has already been refilled.
|
|
40
|
+
*/
|
|
41
|
+
function enforceCap(now) {
|
|
42
|
+
if (windows.size < MAX_TRACKED_KEYS)
|
|
43
|
+
return;
|
|
44
|
+
sweep(now);
|
|
45
|
+
while (windows.size >= MAX_TRACKED_KEYS) {
|
|
46
|
+
const oldest = windows.keys().next();
|
|
47
|
+
if (oldest.done)
|
|
48
|
+
return;
|
|
49
|
+
windows.delete(oldest.value);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Count one request against an in-process window.
|
|
54
|
+
*
|
|
55
|
+
* Fixed window rather than sliding: a sliding window needs per-request
|
|
56
|
+
* timestamps and this is a degraded path, not the primary control. The
|
|
57
|
+
* consequence is that a client can spend its budget at the end of one window and
|
|
58
|
+
* again at the start of the next, which is acceptable for a fallback and would
|
|
59
|
+
* not be for the primary limiter.
|
|
60
|
+
*/
|
|
61
|
+
export function localRateLimit(key, maxAttempts, windowSeconds) {
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
enforceCap(now);
|
|
64
|
+
const existing = windows.get(key);
|
|
65
|
+
if (!existing || existing.resetAt <= now) {
|
|
66
|
+
windows.set(key, { count: 1, resetAt: now + windowSeconds * 1000 });
|
|
67
|
+
return { allowed: true };
|
|
68
|
+
}
|
|
69
|
+
existing.count += 1;
|
|
70
|
+
if (existing.count > maxAttempts) {
|
|
71
|
+
return {
|
|
72
|
+
allowed: false,
|
|
73
|
+
retryAfterSeconds: Math.max(1, Math.ceil((existing.resetAt - now) / 1000)),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return { allowed: true };
|
|
77
|
+
}
|
|
78
|
+
/** Test seam: forget every tracked window. */
|
|
79
|
+
export function resetLocalRateLimits() {
|
|
80
|
+
windows.clear();
|
|
81
|
+
}
|
|
82
|
+
/** Test seam: how many windows are currently tracked. */
|
|
83
|
+
export function localRateLimitSize() {
|
|
84
|
+
return windows.size;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=localRateLimit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localRateLimit.js","sourceRoot":"","sources":["../../src/services/localRateLimit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,uEAAuE;AACvE,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE1C,6EAA6E;AAC7E,SAAS,KAAK,CAAC,GAAW;IACxB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACpC,IAAI,MAAM,CAAC,OAAO,IAAI,GAAG;YAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,OAAO,CAAC,IAAI,GAAG,gBAAgB;QAAE,OAAO;IAC5C,KAAK,CAAC,GAAG,CAAC,CAAC;IACX,OAAO,OAAO,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,MAAM,CAAC,IAAI;YAAE,OAAO;QACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAMD;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,WAAmB,EACnB,aAAqB;IAErB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,UAAU,CAAC,GAAG,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,aAAa,GAAG,IAAI,EAAE,CAAC,CAAC;QACpE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;IACpB,IAAI,QAAQ,CAAC,KAAK,GAAG,WAAW,EAAE,CAAC;QACjC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;SAC3E,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,oBAAoB;IAClC,OAAO,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** True only when the token exists and has already been consumed. */
|
|
2
|
+
export declare function findRefreshTokenState(token: string): Promise<boolean>;
|
|
3
|
+
/** The user a refresh token belongs to, or null if it is not known. */
|
|
4
|
+
export declare function refreshTokenOwner(token: string): Promise<string | null>;
|
|
5
|
+
//# sourceMappingURL=refreshTokenState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refreshTokenState.d.ts","sourceRoot":"","sources":["../../src/services/refreshTokenState.ts"],"names":[],"mappings":"AAiCA,qEAAqE;AACrE,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG3E;AAED,uEAAuE;AACvE,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG7E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { db } from "../db/index.js";
|
|
3
|
+
import { refreshTokens } from "../db/schema.js";
|
|
4
|
+
import { hashToken } from "./tokens.js";
|
|
5
|
+
async function stateOf(token) {
|
|
6
|
+
const [row] = await db
|
|
7
|
+
.select()
|
|
8
|
+
.from(refreshTokens)
|
|
9
|
+
.where(eq(refreshTokens.tokenHash, hashToken(token)))
|
|
10
|
+
.limit(1);
|
|
11
|
+
if (!row)
|
|
12
|
+
return undefined;
|
|
13
|
+
const state = row.revokedAt !== null
|
|
14
|
+
? "revoked"
|
|
15
|
+
: row.expiresAt.getTime() <= Date.now()
|
|
16
|
+
? "expired"
|
|
17
|
+
: "live";
|
|
18
|
+
return { state, userId: row.userId };
|
|
19
|
+
}
|
|
20
|
+
/** True only when the token exists and has already been consumed. */
|
|
21
|
+
export async function findRefreshTokenState(token) {
|
|
22
|
+
const found = await stateOf(token);
|
|
23
|
+
return found?.state === "revoked";
|
|
24
|
+
}
|
|
25
|
+
/** The user a refresh token belongs to, or null if it is not known. */
|
|
26
|
+
export async function refreshTokenOwner(token) {
|
|
27
|
+
const found = await stateOf(token);
|
|
28
|
+
return found?.userId ?? null;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=refreshTokenState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refreshTokenState.js","sourceRoot":"","sources":["../../src/services/refreshTokenState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAcxC,KAAK,UAAU,OAAO,CAAC,KAAa;IAClC,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;SACnB,MAAM,EAAE;SACR,IAAI,CAAC,aAAa,CAAC;SACnB,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;SACpD,KAAK,CAAC,CAAC,CAAC,CAAC;IACZ,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,KAAK,GACT,GAAG,CAAC,SAAS,KAAK,IAAI;QACpB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE;YACrC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;AACvC,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAa;IACvD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;AACpC,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa;IACnD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API key scope registry.
|
|
3
|
+
*
|
|
4
|
+
* API key scopes used to be decorative. `requireScopes` existed and was
|
|
5
|
+
* decorated onto the Fastify instance, but no route referenced it, so a key
|
|
6
|
+
* issued with the default `["api:read"]` carried exactly the same authority as
|
|
7
|
+
* the user who created it. Scopes were also free-form: a caller could request
|
|
8
|
+
* any string at key creation, including the literal `"service_account"` that
|
|
9
|
+
* `requireScopes` treated as a wildcard.
|
|
10
|
+
*
|
|
11
|
+
* A registry fixes both halves. A scope that is not defined here cannot be
|
|
12
|
+
* granted, so there is no string an attacker can invent; and a route that needs a
|
|
13
|
+
* scope names it from this list, so enforcement cannot silently drift out of
|
|
14
|
+
* date the way an unreferenced decorator did.
|
|
15
|
+
*/
|
|
16
|
+
/** Every scope Keystone recognises. Order is the order shown to operators. */
|
|
17
|
+
export declare const API_KEY_SCOPES: {
|
|
18
|
+
/** Read the caller's own profile, sessions, and keys. */
|
|
19
|
+
readonly "profile:read": "Read your own profile and identity";
|
|
20
|
+
readonly "profile:write": "Update your own profile";
|
|
21
|
+
/** Read sessions belonging to the caller. */
|
|
22
|
+
readonly "sessions:read": "List your own sessions";
|
|
23
|
+
readonly "sessions:revoke": "Revoke your own sessions";
|
|
24
|
+
/** Manage the caller's own API keys. */
|
|
25
|
+
readonly "api_keys:read": "List your own API keys";
|
|
26
|
+
readonly "api_keys:revoke": "Revoke your own API keys";
|
|
27
|
+
/** Read organization members and applications. */
|
|
28
|
+
readonly "organizations:read": "Read organization membership and applications";
|
|
29
|
+
/** Manage organization members, applications, and roles. */
|
|
30
|
+
readonly "organizations:write": "Manage organization membership and applications";
|
|
31
|
+
/** Read and manage webhooks. */
|
|
32
|
+
readonly "webhooks:manage": "Create, update, and delete webhooks";
|
|
33
|
+
/** Read and manage workflows. */
|
|
34
|
+
readonly "workflows:read": "Read workflows and their runs";
|
|
35
|
+
readonly "workflows:write": "Create and update workflows";
|
|
36
|
+
/** Second-factor management. Never appropriate for a machine credential. */
|
|
37
|
+
readonly "mfa:manage": "Enroll, verify, and disable TOTP and backup codes";
|
|
38
|
+
};
|
|
39
|
+
export type ApiKeyScope = keyof typeof API_KEY_SCOPES;
|
|
40
|
+
export declare function isApiKeyScope(value: string): value is ApiKeyScope;
|
|
41
|
+
export declare function knownScopes(): ApiKeyScope[];
|
|
42
|
+
/** Human-readable description of a scope, for API responses and dashboards. */
|
|
43
|
+
export declare function describeScope(scope: string): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Scopes granted to a service account by default.
|
|
46
|
+
*
|
|
47
|
+
* Deliberately excludes anything interactive: a machine credential has no user
|
|
48
|
+
* present to complete a second factor, no real profile, and no sessions worth
|
|
49
|
+
* listing. A service account that needs more is granted it explicitly.
|
|
50
|
+
*/
|
|
51
|
+
export declare const SERVICE_ACCOUNT_DEFAULT_SCOPES: ApiKeyScope[];
|
|
52
|
+
/**
|
|
53
|
+
* Scopes a new personal API key receives when the caller names none.
|
|
54
|
+
*
|
|
55
|
+
* Read-only and confined to the caller's own resources. The previous default,
|
|
56
|
+
* `["api:read"]`, was not in the registry at all ā which is a fair indicator that
|
|
57
|
+
* nothing was checking it.
|
|
58
|
+
*/
|
|
59
|
+
export declare const PERSONAL_KEY_DEFAULT_SCOPES: ApiKeyScope[];
|
|
60
|
+
/**
|
|
61
|
+
* Scopes that may never be granted to a machine credential.
|
|
62
|
+
*
|
|
63
|
+
* `mfa:manage` because a second factor is enrolled by a person holding an
|
|
64
|
+
* authenticator; `MfaRequiredError` is raised when a token is minted for a user
|
|
65
|
+
* with TOTP enabled and no recorded factor, and a service account has no
|
|
66
|
+
* authenticator to record.
|
|
67
|
+
*
|
|
68
|
+
* `profile:*` because a service account's "profile" is a synthesized object with
|
|
69
|
+
* an id of `sa:<uuid>` that matches no user row. Reading it returns nothing real,
|
|
70
|
+
* and writing it would update zero rows -- so the scope is meaningless for a
|
|
71
|
+
* machine and misleading in an audit log that shows what a key was used for.
|
|
72
|
+
*/
|
|
73
|
+
export declare const HUMAN_ONLY_SCOPES: readonly ApiKeyScope[];
|
|
74
|
+
export interface ScopeValidation {
|
|
75
|
+
ok: boolean;
|
|
76
|
+
/** Unknown scopes, which must be refused rather than stored. */
|
|
77
|
+
unknown: string[];
|
|
78
|
+
/** Scopes refused because a service account may not hold them. */
|
|
79
|
+
forbiddenForServiceAccount: string[];
|
|
80
|
+
/** The accepted set, de-duplicated and in registry order. */
|
|
81
|
+
scopes: ApiKeyScope[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validate a requested scope set.
|
|
85
|
+
*
|
|
86
|
+
* Unknown scopes are refused rather than dropped. Silently discarding a scope a
|
|
87
|
+
* caller asked for hides both a typo and an attempt to smuggle an unrecognised
|
|
88
|
+
* privilege past a review, and it leaves the caller believing they hold
|
|
89
|
+
* something they do not.
|
|
90
|
+
*/
|
|
91
|
+
export declare function validateScopes(requested: string[] | undefined, options?: {
|
|
92
|
+
principal: "user" | "service_account";
|
|
93
|
+
fallback?: ApiKeyScope[];
|
|
94
|
+
}): ScopeValidation;
|
|
95
|
+
/**
|
|
96
|
+
* Narrow a key's stored scopes to what the caller is actually entitled to.
|
|
97
|
+
*
|
|
98
|
+
* A key never gains authority from its own record. The effective set is what the
|
|
99
|
+
* key holds *intersected with* what its principal could do directly, so revoking
|
|
100
|
+
* a role or removing a membership takes effect on the key too rather than
|
|
101
|
+
* leaving a stale grant behind.
|
|
102
|
+
*/
|
|
103
|
+
export declare function intersectScopes(granted: string[] | null | undefined, principalAllows: string[]): ApiKeyScope[];
|
|
104
|
+
/**
|
|
105
|
+
* Grant check used by `requireScopes`.
|
|
106
|
+
*
|
|
107
|
+
* Explicit allow-list membership only. The previous implementation also accepted
|
|
108
|
+
* a key whose scopes merely *contained* the string `"service_account"`, which is
|
|
109
|
+
* a bypass by construction: that string was client-suppliable at key creation, so
|
|
110
|
+
* any key created with `scopes: ["service_account"]` satisfied every check.
|
|
111
|
+
*/
|
|
112
|
+
export declare function hasScopes(granted: string[] | null | undefined, required: readonly string[]): boolean;
|
|
113
|
+
//# sourceMappingURL=scopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/services/scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,8EAA8E;AAC9E,eAAO,MAAM,cAAc;IACzB,yDAAyD;aACzD,cAAc,EAAE,oCAAoC;aACpD,eAAe,EAAE,yBAAyB;IAC1C,6CAA6C;aAC7C,eAAe,EAAE,wBAAwB;aACzC,iBAAiB,EAAE,0BAA0B;IAC7C,wCAAwC;aACxC,eAAe,EAAE,wBAAwB;aACzC,iBAAiB,EAAE,0BAA0B;IAC7C,kDAAkD;aAClD,oBAAoB,EAAE,+CAA+C;IACrE,4DAA4D;aAC5D,qBAAqB,EAAE,iDAAiD;IACxE,gCAAgC;aAChC,iBAAiB,EAAE,qCAAqC;IACxD,iCAAiC;aACjC,gBAAgB,EAAE,+BAA+B;aACjD,iBAAiB,EAAE,6BAA6B;IAChD,4EAA4E;aAC5E,YAAY,EAAE,mDAAmD;CACzD,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,cAAc,CAAC;AAItD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAEjE;AAED,wBAAgB,WAAW,IAAI,WAAW,EAAE,CAE3C;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,EAAE,WAAW,EAA2B,CAAC;AAEpF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,WAAW,EAAuD,CAAC;AAE7G;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,WAAW,EAInD,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,gEAAgE;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kEAAkE;IAClE,0BAA0B,EAAE,MAAM,EAAE,CAAC;IACrC,6DAA6D;IAC7D,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,EAC/B,OAAO,GAAE;IAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAAC;IAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAA;CAA0B,GACnG,eAAe,CAwBjB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAI9G;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAIpG"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API key scope registry.
|
|
3
|
+
*
|
|
4
|
+
* API key scopes used to be decorative. `requireScopes` existed and was
|
|
5
|
+
* decorated onto the Fastify instance, but no route referenced it, so a key
|
|
6
|
+
* issued with the default `["api:read"]` carried exactly the same authority as
|
|
7
|
+
* the user who created it. Scopes were also free-form: a caller could request
|
|
8
|
+
* any string at key creation, including the literal `"service_account"` that
|
|
9
|
+
* `requireScopes` treated as a wildcard.
|
|
10
|
+
*
|
|
11
|
+
* A registry fixes both halves. A scope that is not defined here cannot be
|
|
12
|
+
* granted, so there is no string an attacker can invent; and a route that needs a
|
|
13
|
+
* scope names it from this list, so enforcement cannot silently drift out of
|
|
14
|
+
* date the way an unreferenced decorator did.
|
|
15
|
+
*/
|
|
16
|
+
/** Every scope Keystone recognises. Order is the order shown to operators. */
|
|
17
|
+
export const API_KEY_SCOPES = {
|
|
18
|
+
/** Read the caller's own profile, sessions, and keys. */
|
|
19
|
+
"profile:read": "Read your own profile and identity",
|
|
20
|
+
"profile:write": "Update your own profile",
|
|
21
|
+
/** Read sessions belonging to the caller. */
|
|
22
|
+
"sessions:read": "List your own sessions",
|
|
23
|
+
"sessions:revoke": "Revoke your own sessions",
|
|
24
|
+
/** Manage the caller's own API keys. */
|
|
25
|
+
"api_keys:read": "List your own API keys",
|
|
26
|
+
"api_keys:revoke": "Revoke your own API keys",
|
|
27
|
+
/** Read organization members and applications. */
|
|
28
|
+
"organizations:read": "Read organization membership and applications",
|
|
29
|
+
/** Manage organization members, applications, and roles. */
|
|
30
|
+
"organizations:write": "Manage organization membership and applications",
|
|
31
|
+
/** Read and manage webhooks. */
|
|
32
|
+
"webhooks:manage": "Create, update, and delete webhooks",
|
|
33
|
+
/** Read and manage workflows. */
|
|
34
|
+
"workflows:read": "Read workflows and their runs",
|
|
35
|
+
"workflows:write": "Create and update workflows",
|
|
36
|
+
/** Second-factor management. Never appropriate for a machine credential. */
|
|
37
|
+
"mfa:manage": "Enroll, verify, and disable TOTP and backup codes",
|
|
38
|
+
};
|
|
39
|
+
const ALL_SCOPES = Object.keys(API_KEY_SCOPES);
|
|
40
|
+
export function isApiKeyScope(value) {
|
|
41
|
+
return Object.prototype.hasOwnProperty.call(API_KEY_SCOPES, value);
|
|
42
|
+
}
|
|
43
|
+
export function knownScopes() {
|
|
44
|
+
return [...ALL_SCOPES];
|
|
45
|
+
}
|
|
46
|
+
/** Human-readable description of a scope, for API responses and dashboards. */
|
|
47
|
+
export function describeScope(scope) {
|
|
48
|
+
return isApiKeyScope(scope) ? API_KEY_SCOPES[scope] : undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Scopes granted to a service account by default.
|
|
52
|
+
*
|
|
53
|
+
* Deliberately excludes anything interactive: a machine credential has no user
|
|
54
|
+
* present to complete a second factor, no real profile, and no sessions worth
|
|
55
|
+
* listing. A service account that needs more is granted it explicitly.
|
|
56
|
+
*/
|
|
57
|
+
export const SERVICE_ACCOUNT_DEFAULT_SCOPES = ["organizations:read"];
|
|
58
|
+
/**
|
|
59
|
+
* Scopes a new personal API key receives when the caller names none.
|
|
60
|
+
*
|
|
61
|
+
* Read-only and confined to the caller's own resources. The previous default,
|
|
62
|
+
* `["api:read"]`, was not in the registry at all ā which is a fair indicator that
|
|
63
|
+
* nothing was checking it.
|
|
64
|
+
*/
|
|
65
|
+
export const PERSONAL_KEY_DEFAULT_SCOPES = ["profile:read", "sessions:read", "api_keys:read"];
|
|
66
|
+
/**
|
|
67
|
+
* Scopes that may never be granted to a machine credential.
|
|
68
|
+
*
|
|
69
|
+
* `mfa:manage` because a second factor is enrolled by a person holding an
|
|
70
|
+
* authenticator; `MfaRequiredError` is raised when a token is minted for a user
|
|
71
|
+
* with TOTP enabled and no recorded factor, and a service account has no
|
|
72
|
+
* authenticator to record.
|
|
73
|
+
*
|
|
74
|
+
* `profile:*` because a service account's "profile" is a synthesized object with
|
|
75
|
+
* an id of `sa:<uuid>` that matches no user row. Reading it returns nothing real,
|
|
76
|
+
* and writing it would update zero rows -- so the scope is meaningless for a
|
|
77
|
+
* machine and misleading in an audit log that shows what a key was used for.
|
|
78
|
+
*/
|
|
79
|
+
export const HUMAN_ONLY_SCOPES = [
|
|
80
|
+
"mfa:manage",
|
|
81
|
+
"profile:read",
|
|
82
|
+
"profile:write",
|
|
83
|
+
];
|
|
84
|
+
/**
|
|
85
|
+
* Validate a requested scope set.
|
|
86
|
+
*
|
|
87
|
+
* Unknown scopes are refused rather than dropped. Silently discarding a scope a
|
|
88
|
+
* caller asked for hides both a typo and an attempt to smuggle an unrecognised
|
|
89
|
+
* privilege past a review, and it leaves the caller believing they hold
|
|
90
|
+
* something they do not.
|
|
91
|
+
*/
|
|
92
|
+
export function validateScopes(requested, options = { principal: "user" }) {
|
|
93
|
+
const wanted = requested && requested.length > 0
|
|
94
|
+
? requested
|
|
95
|
+
: (options.fallback ??
|
|
96
|
+
(options.principal === "service_account" ? SERVICE_ACCOUNT_DEFAULT_SCOPES : PERSONAL_KEY_DEFAULT_SCOPES));
|
|
97
|
+
const unknown = wanted.filter((scope) => !isApiKeyScope(scope));
|
|
98
|
+
const known = wanted.filter(isApiKeyScope);
|
|
99
|
+
const forbidden = options.principal === "service_account"
|
|
100
|
+
? known.filter((scope) => HUMAN_ONLY_SCOPES.includes(scope))
|
|
101
|
+
: [];
|
|
102
|
+
const allowed = known.filter((scope) => !forbidden.includes(scope));
|
|
103
|
+
return {
|
|
104
|
+
ok: unknown.length === 0 && forbidden.length === 0,
|
|
105
|
+
unknown,
|
|
106
|
+
forbiddenForServiceAccount: forbidden,
|
|
107
|
+
// Registry order, so two equivalent requests produce identical rows.
|
|
108
|
+
scopes: ALL_SCOPES.filter((scope) => allowed.includes(scope)),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Narrow a key's stored scopes to what the caller is actually entitled to.
|
|
113
|
+
*
|
|
114
|
+
* A key never gains authority from its own record. The effective set is what the
|
|
115
|
+
* key holds *intersected with* what its principal could do directly, so revoking
|
|
116
|
+
* a role or removing a membership takes effect on the key too rather than
|
|
117
|
+
* leaving a stale grant behind.
|
|
118
|
+
*/
|
|
119
|
+
export function intersectScopes(granted, principalAllows) {
|
|
120
|
+
const held = new Set((granted ?? []).filter(isApiKeyScope));
|
|
121
|
+
const allowed = new Set(principalAllows.filter(isApiKeyScope));
|
|
122
|
+
return ALL_SCOPES.filter((scope) => held.has(scope) && allowed.has(scope));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Grant check used by `requireScopes`.
|
|
126
|
+
*
|
|
127
|
+
* Explicit allow-list membership only. The previous implementation also accepted
|
|
128
|
+
* a key whose scopes merely *contained* the string `"service_account"`, which is
|
|
129
|
+
* a bypass by construction: that string was client-suppliable at key creation, so
|
|
130
|
+
* any key created with `scopes: ["service_account"]` satisfied every check.
|
|
131
|
+
*/
|
|
132
|
+
export function hasScopes(granted, required) {
|
|
133
|
+
if (required.length === 0)
|
|
134
|
+
return true;
|
|
135
|
+
const held = new Set(granted ?? []);
|
|
136
|
+
return required.every((scope) => held.has(scope));
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/services/scopes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
export declare function getSetupToken(): string | undefined;
|
|
2
2
|
export declare function generateSetupToken(): string;
|
|
3
3
|
export declare function validateSetupToken(token: string | undefined): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Report where the setup token is, without printing it.
|
|
6
|
+
*
|
|
7
|
+
* The token used to be written to stdout in cleartext. That is convenient once
|
|
8
|
+
* and permanent afterwards: the line lands in container logs, in journald, and in
|
|
9
|
+
* whatever ships logs off the host, where it stays readable to anyone who can
|
|
10
|
+
* read them and outlives the bootstrap it was for.
|
|
11
|
+
*
|
|
12
|
+
* The token is a full account-initialisation credential, so it is now only
|
|
13
|
+
* printed when an operator asks for it explicitly with
|
|
14
|
+
* `KEYSTONE_PRINT_SETUP_TOKEN=true`, and never in production.
|
|
15
|
+
*/
|
|
4
16
|
export declare function printSetupToken(): void;
|
|
5
17
|
//# sourceMappingURL=token.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/services/setup/token.ts"],"names":[],"mappings":"AAMA,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/services/setup/token.ts"],"names":[],"mappings":"AAMA,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAK3C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAgBrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAsBtC"}
|
|
@@ -20,18 +20,42 @@ export function validateSetupToken(token) {
|
|
|
20
20
|
const cleanToken = token.trim().toLowerCase();
|
|
21
21
|
const cleanExpected = expected.trim().toLowerCase();
|
|
22
22
|
if (cleanToken.length !== cleanExpected.length) {
|
|
23
|
-
|
|
23
|
+
// Deliberately silent. The previous line logged both lengths, which
|
|
24
|
+
// discloses the length of the expected token to anyone who can see the
|
|
25
|
+
// output, and told an operator nothing they could act on.
|
|
24
26
|
return false;
|
|
25
27
|
}
|
|
26
28
|
return crypto.timingSafeEqual(Buffer.from(cleanToken), Buffer.from(cleanExpected));
|
|
27
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Report where the setup token is, without printing it.
|
|
32
|
+
*
|
|
33
|
+
* The token used to be written to stdout in cleartext. That is convenient once
|
|
34
|
+
* and permanent afterwards: the line lands in container logs, in journald, and in
|
|
35
|
+
* whatever ships logs off the host, where it stays readable to anyone who can
|
|
36
|
+
* read them and outlives the bootstrap it was for.
|
|
37
|
+
*
|
|
38
|
+
* The token is a full account-initialisation credential, so it is now only
|
|
39
|
+
* printed when an operator asks for it explicitly with
|
|
40
|
+
* `KEYSTONE_PRINT_SETUP_TOKEN=true`, and never in production.
|
|
41
|
+
*/
|
|
28
42
|
export function printSetupToken() {
|
|
29
43
|
const token = getSetupToken();
|
|
30
|
-
if (token)
|
|
44
|
+
if (!token)
|
|
45
|
+
return;
|
|
46
|
+
const port = process.env.PORT || 4001;
|
|
47
|
+
const explicit = process.env.KEYSTONE_PRINT_SETUP_TOKEN === "true";
|
|
48
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
49
|
+
if (explicit && !isProduction) {
|
|
31
50
|
// eslint-disable-next-line no-console
|
|
32
51
|
console.log(`\nš Keystone setup token: ${token}\n`);
|
|
33
52
|
// eslint-disable-next-line no-console
|
|
34
|
-
console.log(` Use this token to complete setup at http://localhost:${
|
|
53
|
+
console.log(` Use this token to complete setup at http://localhost:${port}/setup\n`);
|
|
54
|
+
return;
|
|
35
55
|
}
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
57
|
+
console.log(`š A setup token is required to complete setup at http://localhost:${port}/setup\n` +
|
|
58
|
+
` It was not printed. Read it from ${SETUP_TOKEN_ENV}, or set ` +
|
|
59
|
+
`KEYSTONE_PRINT_SETUP_TOKEN=true outside production to display it once.`);
|
|
36
60
|
}
|
|
37
61
|
//# sourceMappingURL=token.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/services/setup/token.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAE/C,IAAI,cAAc,GAAkB,IAAI,CAAC;AAEzC,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,cAAc,IAAI,SAAS,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,0EAA0E;IAC1E,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpD,IAAI,UAAU,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,EAAE,CAAC;QAC/C,
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/services/setup/token.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAE/C,IAAI,cAAc,GAAkB,IAAI,CAAC;AAEzC,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,cAAc,IAAI,SAAS,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,0EAA0E;IAC1E,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpD,IAAI,UAAU,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,EAAE,CAAC;QAC/C,oEAAoE;QACpE,uEAAuE;QACvE,0DAA0D;QAC1D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;IACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,MAAM,CAAC;IACnE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;IAE3D,IAAI,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;QAC9B,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,8BAA8B,KAAK,IAAI,CAAC,CAAC;QACrD,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,2DAA2D,IAAI,UAAU,CAAC,CAAC;QACvF,OAAO;IACT,CAAC;IAED,sCAAsC;IACtC,OAAO,CAAC,GAAG,CACT,sEAAsE,IAAI,UAAU;QAClF,uCAAuC,eAAe,WAAW;QACjE,wEAAwE,CAC3E,CAAC;AACJ,CAAC"}
|
|
@@ -90,5 +90,6 @@ export declare function verifyAccessToken(token: string): Promise<TokenClaims>;
|
|
|
90
90
|
export declare function rotateRefreshToken(token: string, ip?: string, userAgent?: string, clientId?: string, expectedAppId?: string): Promise<TokenSet | null>;
|
|
91
91
|
export declare function revokeRefreshToken(token: string): Promise<void>;
|
|
92
92
|
export declare function revokeAllUserRefreshTokens(userId: string): Promise<void>;
|
|
93
|
+
export declare function hashToken(token: string): string;
|
|
93
94
|
export { hashApiKey, generateApiKey } from "./secrets.js";
|
|
94
95
|
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"AAWA,OAAO,EAKL,KAAK,IAAI,EACT,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa/C,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAerD;AAED;;;GAGG;AACH,wBAAsB,YAAY,gCAGjC;AAED;;;GAGG;AACH,wBAAsB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GASlC;AAMD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3E;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,EAIzB;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6B5F;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,WAAW,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,EAAE,CAAC,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,GAAE,kBAAuB,EAC7B,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,QAAQ,CAAC,CAiCnB;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgB3E;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,EAAE,CAAC,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAmF1B;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E;
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"AAWA,OAAO,EAKL,KAAK,IAAI,EACT,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa/C,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAerD;AAED;;;GAGG;AACH,wBAAsB,YAAY,gCAGjC;AAED;;;GAGG;AACH,wBAAsB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GASlC;AAMD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE3E;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,MAAM,EAAE,MAAM,EAIzB;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6B5F;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,WAAW,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,EAAE,CAAC,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,GAAE,kBAAuB,EAC7B,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,QAAQ,CAAC,CAiCnB;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgB3E;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,EAAE,CAAC,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAmF1B;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAGD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/services/tokens.js
CHANGED
|
@@ -263,7 +263,7 @@ export async function revokeRefreshToken(token) {
|
|
|
263
263
|
export async function revokeAllUserRefreshTokens(userId) {
|
|
264
264
|
await db.update(refreshTokens).set({ revokedAt: new Date() }).where(eq(refreshTokens.userId, userId));
|
|
265
265
|
}
|
|
266
|
-
function hashToken(token) {
|
|
266
|
+
export function hashToken(token) {
|
|
267
267
|
return crypto.createHash("sha256").update(token).digest("hex");
|
|
268
268
|
}
|
|
269
269
|
// Re-exported from secrets service for backwards compatibility.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EACT,qBAAqB,EACrB,SAAS,GACV,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EACL,aAAa,EACb,KAAK,EACL,YAAY,EACZ,cAAc,GAGf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GAErB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D,mDAAmD;AACnD,IAAI,SAAS,GAA0B,IAAI,CAAC;AAC5C,iFAAiF;AACjF,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACtE,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACnE,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;QACpD,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,SAAS,GAAG,MAAM,mBAAmB,EAAE,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAC1C,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,SAAS;QAAE,MAAM,eAAe,EAAE,CAAC;IACxC,OAAO,SAAS,CAAC,SAAU,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,MAAM,eAAe,EAAE,CAAC;IAClD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAC5B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC/C,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,OAAO,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;IACrE,CAAC,CAAC,CACH,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,MAAM;IACb,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,oBAAoB,MAAM,CAAC,IAAI,EAAE,CAAC;AAC9E,CAAC;AASD;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,GAAG,cAAuB,CAAC;IAC/B,MAAM,CAAS;IAExB,YAAY,MAAc;QACxB,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAaD,MAAM,UAAU,iBAAiB,CAAC,IAAU,EAAE,IAAI,GAAuB,EAAE;IACzE,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACtF,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAgB;QAC1B,GAAG,EAAE,IAAI,CAAC,EAAE;QACZ,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,SAAS;QAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;QAC9C,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC;IACF,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;IAC3C,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;IAC3C,IAAI,IAAI,CAAC,QAAQ;QAAE,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;IACpD,IAAI,IAAI,CAAC,iBAAiB;QAAE,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,CAAC;IAC/E,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;QACnC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,MAA4C,CAAC;SAC7D,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC;SACtE,WAAW,EAAE;SACb,SAAS,CAAC,MAAM,EAAE,CAAC;SACnB,WAAW,CAAC,SAAS,CAAC;SACtB,iBAAiB,CAAC,GAAG,MAAM,CAAC,wBAAwB,GAAG,CAAC;SACxD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AASD,MAAM,UAAU,4BAA4B,CAC1C,IAAmC;IAEnC,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC/D,MAAM,MAAM,GAA4B;QACtC,GAAG,EAAE,IAAI,CAAC,QAAQ;QAClB,SAAS,EAAE,IAAI,CAAC,QAAQ;QACxB,MAAM,EAAE,IAAI,CAAC,KAAK;QAClB,MAAM,EAAE,IAAI,CAAC,KAAK;KACnB,CAAC;IACF,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;SACvB,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC;SACtE,WAAW,EAAE;SACb,SAAS,CAAC,MAAM,EAAE,CAAC;SACnB,WAAW,CAAC,SAAS,CAAC;SACtB,iBAAiB,CAAC,GAAG,MAAM,CAAC,wBAAwB,GAAG,CAAC;SACxD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAU,EACV,GAAgB,EAChB,KAAc;IAEd,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC/D,MAAM,MAAM,GAA4B;QACtC,GAAG,EAAE,IAAI,CAAC,EAAE;QACZ,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,cAAc,EAAE,IAAI,CAAC,aAAa;QAClC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,SAAS;QACvB,GAAG,EAAE,GAAG,CAAC,QAAQ;QACjB,GAAG,EAAE,GAAG,CAAC,QAAQ;KAClB,CAAC;IACF,IAAI,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;IAChC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;SACvB,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC;SACtE,WAAW,EAAE;SACb,SAAS,CAAC,MAAM,EAAE,CAAC;SACnB,iBAAiB,CAAC,GAAG,MAAM,CAAC,wBAAwB,GAAG,CAAC;SACxD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAU,EACV,EAAW,EACX,SAAkB,EAClB,IAAI,GAAuB,EAAE,EAC7B,iBAA0B;IAE1B,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAClE,MAAM,gBAAgB,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;IAEjF,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;QACvD,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI;QACzB,SAAS,EAAE,gBAAgB;QAC3B,SAAS;QACT,SAAS,EAAE,EAAE,IAAI,IAAI;QACrB,SAAS,EAAE,SAAS,IAAI,IAAI;QAC5B,iBAAiB,EAAE,iBAAiB,IAAI,IAAI;QAC5C,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;QACjC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;KAC1B,CAAC,CAAC,SAAS,EAAE,CAAC;IAEf,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACzC,MAAM,QAAQ,CAAC,MAAM,CAAC;YACpB,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,cAAc,EAAE,QAAQ,CAAC,EAAE;YAC3B,iBAAiB;YACjB,SAAS,EAAE,EAAE;YACb,SAAS;YACT,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;IACjF,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;AACrF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa;IACnD,IAAI,CAAC,SAAS;QAAE,MAAM,eAAe,EAAE,CAAC;IAExC,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,SAAS,EAAE,SAAS,CAAC;IAE7D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE;QACpD,MAAM,EAAE,MAAM,EAAE;QAChB,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;IACH,OAAO,OAAiC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa,EACb,EAAW,EACX,SAAkB,EAClB,QAAiB,EACjB,aAAsB;IAEtB,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;SACxB,MAAM,EAAE;SACR,IAAI,CAAC,aAAa,CAAC;SACnB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,EACjC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,GAAG,CAAC,EAChC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAChC,CACF;SACA,KAAK,CAAC,CAAC,CAAC,CAAC;IACZ,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,IAAI,EAAE,QAAQ,IAAI,IAAI,CAAC,qBAAqB;QAAE,OAAO,IAAI,CAAC;IAE/D,6EAA6E;IAC7E,wEAAwE;IACxE,qDAAqD;IACrD,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAEzD,IAAI,KAAyB,CAAC;IAC9B,IAAI,KAAyB,CAAC;IAC9B,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,aAAa,IAAI,aAAa,KAAK,QAAQ,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACnE,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,EAAE;aAC3B,MAAM,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC;aAC3F,IAAI,CAAC,YAAY,CAAC;aAClB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;aAChF,KAAK,CAAC,CAAC,CAAC,CAAC;QACZ,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,IAAI,WAAW,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAEhF,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,EAAE;aAC1B,MAAM,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE,CAAC;aACjC,IAAI,CAAC,cAAc,CAAC;aACpB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC3F,KAAK,CAAC,CAAC,CAAC,CAAC;QACZ,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAC7B,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC;QACvB,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;IAC5B,CAAC;SAAM,IAAI,QAAQ,IAAI,aAAa,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2EAA2E;IAC3E,sEAAsE;IACtE,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;SACvB,MAAM,CAAC,aAAa,CAAC;SACrB,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;SACvB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,EACjC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,EACjC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,GAAG,CAAC,EAChC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAChC,CACF;SACA,SAAS,EAAE,CAAC;IACf,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,OAAO,cAAc,CACnB,IAAI,EACJ,EAAE,EACF,SAAS,EACT;QACE,KAAK;QACL,KAAK;QACL,QAAQ;QACR,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,SAAS;QACzD,yEAAyE;QACzE,2EAA2E;QAC3E,gCAAgC;QAChC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,OAAO,CAAC,SAAS;YACnB,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAyB,EAAE;YAClD,CAAC,CAAC,EAAE,CAAC;KACR,EACD,OAAO,CAAC,iBAAiB,IAAI,SAAS,CACvC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAAa;IACpD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;AACzG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,MAAc;IAC7D,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AACxG,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AAED,gEAAgE;AAChE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/services/tokens.ts"],"names":[],"mappings":"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"}
|