@agentlogin/issuer 0.0.0-stage → 0.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +237 -2
  3. package/dist/agents.d.ts +40 -0
  4. package/dist/agents.js +257 -0
  5. package/dist/agents.js.map +1 -0
  6. package/dist/app.d.ts +3 -0
  7. package/dist/app.js +652 -0
  8. package/dist/app.js.map +1 -0
  9. package/dist/clients.d.ts +20 -0
  10. package/dist/clients.js +272 -0
  11. package/dist/clients.js.map +1 -0
  12. package/dist/constants.d.ts +30 -0
  13. package/dist/constants.js +32 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/context.d.ts +37 -0
  16. package/dist/context.js +2 -0
  17. package/dist/context.js.map +1 -0
  18. package/dist/errors.d.ts +10 -0
  19. package/dist/errors.js +17 -0
  20. package/dist/errors.js.map +1 -0
  21. package/dist/index.d.ts +45 -0
  22. package/dist/index.js +107 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/owner-address.d.ts +2 -0
  25. package/dist/owner-address.js +24 -0
  26. package/dist/owner-address.js.map +1 -0
  27. package/dist/safefetch.d.ts +38 -0
  28. package/dist/safefetch.js +164 -0
  29. package/dist/safefetch.js.map +1 -0
  30. package/dist/server.d.ts +1 -0
  31. package/dist/server.js +89 -0
  32. package/dist/server.js.map +1 -0
  33. package/dist/signing-configuration.d.ts +14 -0
  34. package/dist/signing-configuration.js +35 -0
  35. package/dist/signing-configuration.js.map +1 -0
  36. package/dist/signing-state.d.ts +22 -0
  37. package/dist/signing-state.js +14 -0
  38. package/dist/signing-state.js.map +1 -0
  39. package/dist/sqlite-store.d.ts +24 -0
  40. package/dist/sqlite-store.js +81 -0
  41. package/dist/sqlite-store.js.map +1 -0
  42. package/dist/state.d.ts +30 -0
  43. package/dist/state.js +77 -0
  44. package/dist/state.js.map +1 -0
  45. package/dist/store.d.ts +693 -0
  46. package/dist/store.js +883 -0
  47. package/dist/store.js.map +1 -0
  48. package/dist/tokens.d.ts +37 -0
  49. package/dist/tokens.js +167 -0
  50. package/dist/tokens.js.map +1 -0
  51. package/dist/transactions.d.ts +90 -0
  52. package/dist/transactions.js +449 -0
  53. package/dist/transactions.js.map +1 -0
  54. package/dist/util.d.ts +29 -0
  55. package/dist/util.js +113 -0
  56. package/dist/util.js.map +1 -0
  57. package/package.json +37 -4
  58. package/static/wait.js +42 -0
@@ -0,0 +1,81 @@
1
+ // Durable reference adapter. Mutations use one write transaction; reads never acquire the writer lock.
2
+ import { DatabaseSync } from 'node:sqlite';
3
+ import { READ_METHODS, STORE_METHODS, StoreState } from './store.js';
4
+ /**
5
+ * A deliberately coarse reference adapter: the complete state is one versioned JSON row, and every method executes
6
+ * under BEGIN IMMEDIATE for mutations or a read transaction for queries. No state survives between calls, and no
7
+ * await occurs while a transaction owns the lock. Reads still parse the complete snapshot.
8
+ * Separate connections and processes therefore see every preceding committed change. Use a local filesystem;
9
+ * WAL databases must not be shared over a network filesystem. This design favors auditable guarantees over scale.
10
+ */
11
+ export class SQLiteStore {
12
+ database;
13
+ read;
14
+ write;
15
+ closed = false;
16
+ constructor(path, options = {}) {
17
+ const timeout = options.busyTimeoutMs ?? 5000;
18
+ if (!Number.isSafeInteger(timeout) || timeout < 0 || timeout > 2_147_483_647)
19
+ throw new RangeError('busyTimeoutMs must be a nonnegative 32-bit integer');
20
+ this.database = new DatabaseSync(path, { enableDoubleQuotedStringLiterals: false, allowExtension: false });
21
+ try {
22
+ // PRAGMA works on every supported Node 22 release; DatabaseSync's timeout option arrived later.
23
+ this.database.exec(`PRAGMA busy_timeout = ${timeout}`);
24
+ this.database.exec('PRAGMA journal_mode = WAL');
25
+ this.database.exec('PRAGMA synchronous = FULL');
26
+ this.database.exec('CREATE TABLE IF NOT EXISTS agentlogin_state (id INTEGER PRIMARY KEY CHECK (id = 1), snapshot TEXT NOT NULL)');
27
+ this.database.prepare('INSERT OR IGNORE INTO agentlogin_state (id, snapshot) VALUES (1, ?)').run(new StoreState().exportSnapshot());
28
+ this.read = this.database.prepare('SELECT snapshot FROM agentlogin_state WHERE id = 1');
29
+ this.write = this.database.prepare('UPDATE agentlogin_state SET snapshot = ? WHERE id = 1');
30
+ }
31
+ catch (error) {
32
+ this.database.close();
33
+ throw error;
34
+ }
35
+ return new Proxy(this, {
36
+ get: (target, property) => {
37
+ const method = Object.getOwnPropertyDescriptor(StoreState.prototype, property)?.value;
38
+ if (typeof method === 'function' && STORE_METHODS.includes(property)) {
39
+ return async (...args) => target.perform(method, args, READ_METHODS.has(property));
40
+ }
41
+ const value = Reflect.get(target, property, target);
42
+ return typeof value === 'function' ? value.bind(target) : value;
43
+ },
44
+ });
45
+ }
46
+ perform(method, args, readOnly) {
47
+ if (this.closed)
48
+ throw new Error('SQLiteStore is closed');
49
+ this.database.exec(readOnly ? 'BEGIN' : 'BEGIN IMMEDIATE');
50
+ try {
51
+ const snapshot = this.read.get()?.snapshot;
52
+ if (typeof snapshot !== 'string')
53
+ throw new Error('Missing issuer store snapshot');
54
+ const state = new StoreState(snapshot);
55
+ const result = Reflect.apply(method, state, args);
56
+ // Enforce the adapter contract if a future StoreState change accidentally introduces an asynchronous method.
57
+ if (result && typeof result.then === 'function')
58
+ throw new Error('StoreState operations must be synchronous');
59
+ if (!readOnly)
60
+ this.write.run(state.exportSnapshot());
61
+ this.database.exec('COMMIT');
62
+ return result;
63
+ }
64
+ catch (error) {
65
+ // Certain SQLite failures already roll the transaction back. A failed ROLLBACK must not hide the cause.
66
+ try {
67
+ this.database.exec('ROLLBACK');
68
+ }
69
+ catch { /* already rolled back or unusable connection */ }
70
+ throw error;
71
+ }
72
+ }
73
+ /** Close this connection after requests have drained. Safe to call more than once. */
74
+ close() {
75
+ if (this.closed)
76
+ return;
77
+ this.database.close();
78
+ this.closed = true;
79
+ }
80
+ }
81
+ //# sourceMappingURL=sqlite-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-store.js","sourceRoot":"","sources":["../src/sqlite-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { IssuerContext } from './context.js';
2
+ import { type DenyReason, type SubjectFilter, type Transaction, type TransitionEffects } from './store.js';
3
+ /** The transaction as it stands now. Expiry is a function of time, not a stored status (Section 6.2). */
4
+ export declare function effective(ctx: IssuerContext, tx: Transaction): Transaction;
5
+ /** A copy of `tx` in a terminal status. */
6
+ export declare function ended(ctx: IssuerContext, tx: Transaction, status: 'completed' | 'denied', reason?: DenyReason): Transaction;
7
+ /** Writes `next` if the transaction is still at `expectedVersion`. On success `next.version` is the stored version. */
8
+ export declare function commit(ctx: IssuerContext, next: Transaction, expectedVersion: number, effects?: Omit<TransitionEffects, 'now'>): Promise<boolean>;
9
+ /**
10
+ * Ends a transaction as `denied`, whatever else is happening to it: retried until it is terminal. Returns the
11
+ * transaction as it ended, which may be an outcome another request reached first.
12
+ */
13
+ export declare function denyTransaction(ctx: IssuerContext, id: string, reason: DenyReason): Promise<Transaction | undefined>;
14
+ /** Ends every open transaction that matches; `asserted` limits it to transactions past step 7 of Section 6.3. */
15
+ export declare function denyOpenTransactions(ctx: IssuerContext, filter: SubjectFilter, reason: DenyReason, asserted?: boolean): Promise<void>;
16
+ /** What a transaction, code or Access Token is bound to. */
17
+ export interface Subject {
18
+ handle: string;
19
+ kid: string;
20
+ keyEnrollment: string;
21
+ clientId: string;
22
+ agentSub: string;
23
+ agentVersion: number;
24
+ accountVersion: number;
25
+ }
26
+ /**
27
+ * Whether the subject still stands (Sections 3.3, 7.4): the asserting key is the same enrollment, active and
28
+ * unexpired; the Agent exists and is enabled; the Account is not disabled. Otherwise the reason it does not.
29
+ */
30
+ export declare function subjectState(ctx: IssuerContext, s: Subject): Promise<null | 'key_revoked' | 'access_denied'>;
package/dist/state.js ADDED
@@ -0,0 +1,77 @@
1
+ import { isAssertionSubjectError, isAssertionWindowError, isTransactionExpiredError, isTransactionTokenError, TERMINAL } from './store.js';
2
+ import { OAuthError } from './errors.js';
3
+ /** The transaction as it stands now. Expiry is a function of time, not a stored status (Section 6.2). */
4
+ export function effective(ctx, tx) {
5
+ if (!TERMINAL.has(tx.status) && ctx.now() >= tx.expiresAt)
6
+ return { ...tx, status: 'expired', terminalAt: tx.expiresAt, challenge: undefined };
7
+ return tx;
8
+ }
9
+ /** A copy of `tx` in a terminal status. */
10
+ export function ended(ctx, tx, status, reason) {
11
+ return { ...tx, status, reason: reason ?? tx.reason, terminalAt: ctx.now(), challenge: undefined };
12
+ }
13
+ /** Writes `next` if the transaction is still at `expectedVersion`. On success `next.version` is the stored version. */
14
+ export async function commit(ctx, next, expectedVersion, effects = {}) {
15
+ let updated;
16
+ try {
17
+ updated = await ctx.store.updateTransaction(next, expectedVersion, { ...effects, now: ctx.now() });
18
+ }
19
+ catch (error) {
20
+ // An external adapter can load a separate copy of the issuer package (including source vs dist in tests).
21
+ if (isAssertionSubjectError(error))
22
+ throw new OAuthError(401, error.error);
23
+ if (isTransactionExpiredError(error))
24
+ throw new OAuthError(410, 'transaction_expired');
25
+ if (isTransactionTokenError(error))
26
+ throw new OAuthError(401, 'invalid_token', undefined, { 'WWW-Authenticate': 'Bearer error="invalid_token"' });
27
+ if (isAssertionWindowError(error)) {
28
+ throw new OAuthError(400, 'invalid_assertion', 'assertion expired while awaiting acceptance');
29
+ }
30
+ throw error;
31
+ }
32
+ if (updated)
33
+ Object.assign(next, updated);
34
+ return updated !== undefined;
35
+ }
36
+ /**
37
+ * Ends a transaction as `denied`, whatever else is happening to it: retried until it is terminal. Returns the
38
+ * transaction as it ended, which may be an outcome another request reached first.
39
+ */
40
+ export async function denyTransaction(ctx, id, reason) {
41
+ for (;;) {
42
+ const stored = await ctx.store.getTransaction(id);
43
+ if (!stored)
44
+ return undefined;
45
+ const cur = effective(ctx, stored);
46
+ if (TERMINAL.has(cur.status))
47
+ return cur;
48
+ const next = ended(ctx, cur, 'denied', reason);
49
+ if (await commit(ctx, next, stored.version)) {
50
+ return next;
51
+ }
52
+ }
53
+ }
54
+ /** Ends every open transaction that matches; `asserted` limits it to transactions past step 7 of Section 6.3. */
55
+ export async function denyOpenTransactions(ctx, filter, reason, asserted = false) {
56
+ for (const t of await ctx.store.listOpenTransactions(filter)) {
57
+ if (!asserted || t.assertedAt !== undefined)
58
+ await denyTransaction(ctx, t.id, reason);
59
+ }
60
+ }
61
+ /**
62
+ * Whether the subject still stands (Sections 3.3, 7.4): the asserting key is the same enrollment, active and
63
+ * unexpired; the Agent exists and is enabled; the Account is not disabled. Otherwise the reason it does not.
64
+ */
65
+ export async function subjectState(ctx, s) {
66
+ const key = await ctx.store.getKey(s.kid, s.handle);
67
+ if (!key || key.handle !== s.handle || key.enrollment !== s.keyEnrollment || key.agentSub !== s.agentSub || key.status !== 'active' || (await ctx.store.currentTime(ctx.now())) >= key.expiresAt)
68
+ return 'key_revoked';
69
+ const agent = await ctx.store.getAgent(s.handle);
70
+ if (!agent || agent.sub !== s.agentSub || !agent.enabled || agent.authorizationVersion !== s.agentVersion)
71
+ return 'access_denied';
72
+ const account = await ctx.store.getAccount(s.handle, s.clientId);
73
+ if (account?.status === 'disabled' || (account?.authorizationVersion ?? 0) !== s.accountVersion)
74
+ return 'access_denied';
75
+ return null;
76
+ }
77
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}