@aooth/auth 0.1.7 → 0.1.9

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.
@@ -24,26 +24,32 @@ export interface AoothAuthCredential {
24
24
  kind?: string
25
25
 
26
26
  /**
27
- * Custom claims, stored as JSON. Pattern-property shape accepts any key
28
- * with a scalar value matches the JWT registered-claim spec (iss, sub,
29
- * iat, exp, jti, aud, etc.) which are all primitives. Consumers needing
30
- * nested/structured claims should subclass with an explicit `claims` shape.
27
+ * Display metadata: ip, userAgent, fingerprint, label, plus the semantic
28
+ * credential kind (`cli-session` / `pat` / …) folded in by `issue()`. The
29
+ * `@db.json` column is schema-validated, so every field `CredentialMetadata`
30
+ * may carry must be declared here.
31
31
  */
32
32
  @db.json
33
- claims?: {
34
- [/.*/]: string | number | boolean
35
- }
36
-
37
- /** Display metadata: ip, userAgent, fingerprint, label. */
38
- @db.json
39
33
  metadata?: {
40
34
  ip?: string
41
35
  userAgent?: string
42
36
  fingerprint?: string
43
37
  label?: string
38
+ credentialKind?: string
44
39
  }
45
40
 
46
41
  /** Set by refresh-token rotation. */
47
42
  parentCredentialId?: string
48
43
  rotatedAt?: number.timestamp
44
+
45
+ /**
46
+ * Stable session-family id. Minted once at login, copied forward on every
47
+ * rotation. Indexed so a store could group/revoke a family natively (the
48
+ * orchestrator groups in-memory today, but the index is cheap + forward-looking).
49
+ */
50
+ @db.index.plain
51
+ sessionId?: string
52
+
53
+ /** Last-activity timestamp; written only under `trackLastSeen`. */
54
+ lastSeenAt?: number.timestamp
49
55
  }
@@ -0,0 +1,68 @@
1
+ // prettier-ignore-start
2
+ /* eslint-disable */
3
+ /* oxlint-disable */
4
+ /// <reference path="./auth-credential.as" />
5
+ /**
6
+ * 🪄 This file was generated by Atscript
7
+ * Do not edit this file!
8
+ */
9
+
10
+ import type { TAtscriptTypeObject, TAtscriptTypeComplex, TAtscriptTypeFinal, TAtscriptTypeArray, TAtscriptAnnotatedType, TMetadataMap, Validator, TValidatorOptions } from "@atscript/typescript/utils"
11
+
12
+ /**
13
+ * Atscript interface **AoothAuthCredential**
14
+ * @see {@link ./auth-credential.as:3:18}
15
+ */
16
+ export declare class AoothAuthCredential {
17
+ token: string
18
+ userId: string
19
+ issuedAt: number /* timestamp */
20
+ expiresAt: number /* timestamp */
21
+ kind?: string
22
+ metadata?: {
23
+ ip?: string
24
+ userAgent?: string
25
+ fingerprint?: string
26
+ label?: string
27
+ credentialKind?: string
28
+ }
29
+ parentCredentialId?: string
30
+ rotatedAt?: number /* timestamp */
31
+ sessionId?: string
32
+ lastSeenAt?: number /* timestamp */
33
+ static __is_atscript_annotated_type: true
34
+ static type: TAtscriptTypeObject<keyof AoothAuthCredential, AoothAuthCredential>
35
+ static metadata: TMetadataMap<AtscriptMetadata>
36
+ static validator: (opts?: Partial<TValidatorOptions>) => Validator<typeof AoothAuthCredential>
37
+ /** @deprecated JSON Schema support is disabled. Calling this method will throw a runtime error. To enable, set `jsonSchema: 'lazy'` or `jsonSchema: 'bundle'` in tsPlugin options, or add `@emit.jsonSchema` annotation to individual interfaces. */
38
+ static toJsonSchema: () => any
39
+ /** @deprecated Example Data support is disabled. To enable, set `exampleData: true` in tsPlugin options. */
40
+ static toExampleData?: () => any
41
+ static __flat: {
42
+ "token": string
43
+ "userId": string
44
+ "issuedAt": number /* timestamp */
45
+ "expiresAt": number /* timestamp */
46
+ "kind"?: string
47
+ "metadata"?: string
48
+ "parentCredentialId"?: string
49
+ "rotatedAt"?: number /* timestamp */
50
+ "sessionId"?: string
51
+ "lastSeenAt"?: number /* timestamp */
52
+ }
53
+ static __ownProps: {
54
+ "token": string
55
+ "userId": string
56
+ "issuedAt": number /* timestamp */
57
+ "expiresAt": number /* timestamp */
58
+ "kind"?: string
59
+ "metadata"?: string
60
+ "parentCredentialId"?: string
61
+ "rotatedAt"?: number /* timestamp */
62
+ "sessionId"?: string
63
+ "lastSeenAt"?: number /* timestamp */
64
+ }
65
+
66
+ static __pk: string
67
+ }
68
+ // prettier-ignore-end
@@ -1,124 +0,0 @@
1
- //#region src/credential/types.d.ts
2
- /**
3
- * What a successful auth check produces.
4
- * Generic over TClaims for typed custom claims.
5
- */
6
- interface AuthContext<TClaims extends object = object> {
7
- userId: string;
8
- method: "session" | "token";
9
- credentialId: string;
10
- expiresAt: number;
11
- claims?: TClaims;
12
- }
13
- /**
14
- * Display metadata for stateful credentials.
15
- * Extensible via TypeScript declaration merging:
16
- * declare module '@aooth/auth' {
17
- * interface CredentialMetadata { geoCountry?: string }
18
- * }
19
- */
20
- interface CredentialMetadata {
21
- ip?: string;
22
- userAgent?: string;
23
- fingerprint?: string;
24
- label?: string;
25
- }
26
- /**
27
- * Persisted state of a credential.
28
- */
29
- interface CredentialState<TClaims extends object = object> {
30
- userId: string;
31
- issuedAt: number;
32
- expiresAt: number;
33
- claims?: TClaims;
34
- metadata?: CredentialMetadata;
35
- /**
36
- * Discriminant between access and refresh credentials persisted in the same store.
37
- * Defaults to "access" when omitted.
38
- */
39
- kind?: "access" | "refresh";
40
- /** For rotated refresh tokens — id of the parent credential this one replaced */
41
- parentCredentialId?: string;
42
- /** Timestamp of rotation; used by sliding rotation grace period */
43
- rotatedAt?: number;
44
- }
45
- /**
46
- * Result of issuing a credential or refreshing it.
47
- */
48
- interface IssueResult {
49
- accessToken: string;
50
- refreshToken?: string;
51
- accessExpiresAt: number;
52
- refreshExpiresAt?: number;
53
- }
54
- /**
55
- * Refresh token configuration.
56
- */
57
- interface RefreshConfig {
58
- /** Refresh token lifetime in milliseconds. */
59
- ttl: number;
60
- /**
61
- * Rotation strategy. Defaults to 'sliding'.
62
- *
63
- * Note: 'sliding' grace-period replay tolerance only works against stateful
64
- * stores (e.g. {@link CredentialStoreMemory}). Stateless stores (JWT,
65
- * Encapsulated) cannot mutate an issued token in place; after the first
66
- * rotation the old refresh becomes unusable, so 'sliding' degrades to
67
- * 'always' semantics. Use 'always' explicitly for stateless deployments.
68
- */
69
- rotation?: "none" | "always" | "sliding";
70
- /** Grace period for sliding rotation, in milliseconds. Defaults to 30_000. */
71
- rotationGraceMs?: number;
72
- /** Theft detection hook — invoked when a previously-rotated refresh is reused. */
73
- onRotationReuse?: (state: CredentialState) => void;
74
- }
75
- //#endregion
76
- //#region src/stores/store.d.ts
77
- /**
78
- * Pluggable credential storage. Implementations: Memory, JWT, Encapsulated.
79
- * Same shape works for stateful and stateless stores. Stateless stores treat
80
- * the token as the state itself (sign/encrypt on persist, verify/decrypt on retrieve).
81
- *
82
- * `TClaims` is constrained to `extends object`, which TypeScript widens to
83
- * include arrays, class instances, and `Function`. Pass a plain object type
84
- * (e.g. `{ role: string; tenant: string }`); using arrays/classes will type-
85
- * check but won't survive JSON-serialised stateless storage round-trips.
86
- */
87
- interface CredentialStore<TClaims extends object = object> {
88
- /** Persist state, return token. For stateless stores, token IS the state. */
89
- persist(state: CredentialState<TClaims>, ttl?: number): Promise<string>;
90
- /** Retrieve state from token. Returns null if expired/invalid/revoked. */
91
- retrieve(token: string): Promise<CredentialState<TClaims> | null>;
92
- /** Retrieve + invalidate (single-use). For stateless: needs denylist. */
93
- consume(token: string): Promise<CredentialState<TClaims> | null>;
94
- /**
95
- * Update state. The returned token MAY differ from the input — stateful
96
- * stores typically return the same token, while stateless stores re-issue
97
- * a new token (denylisting the old). Callers must use the returned value.
98
- */
99
- update(token: string, state: CredentialState<TClaims>): Promise<string>;
100
- /** Revoke a single token. For stateless: requires denylist; otherwise throws. */
101
- revoke(token: string): Promise<void>;
102
- /**
103
- * Revoke all credentials for a user. Returns count revoked.
104
- * Stateless stores cannot enumerate individual tokens; they MAY implement
105
- * the cascade via a per-user revocation epoch (see `CredentialStoreJwt`)
106
- * and return a sentinel `1` to indicate "revocation took effect".
107
- */
108
- revokeAllForUser(userId: string): Promise<number>;
109
- /** List active credentials for a user (stateful only). */
110
- listForUser?(userId: string): Promise<Array<CredentialState<TClaims> & {
111
- token: string;
112
- }>>;
113
- }
114
- /**
115
- * Denylist for stateless revocation. Stores revoked-but-not-yet-expired token IDs.
116
- * Auto-bounded by token TTLs.
117
- */
118
- interface DenylistStore {
119
- add(jti: string, expiresAt: number): Promise<void>;
120
- has(jti: string): Promise<boolean>;
121
- cleanup(): Promise<number>;
122
- }
123
- //#endregion
124
- export { CredentialState as a, CredentialMetadata as i, DenylistStore as n, IssueResult as o, AuthContext as r, RefreshConfig as s, CredentialStore as t };
@@ -1,124 +0,0 @@
1
- //#region src/credential/types.d.ts
2
- /**
3
- * What a successful auth check produces.
4
- * Generic over TClaims for typed custom claims.
5
- */
6
- interface AuthContext<TClaims extends object = object> {
7
- userId: string;
8
- method: "session" | "token";
9
- credentialId: string;
10
- expiresAt: number;
11
- claims?: TClaims;
12
- }
13
- /**
14
- * Display metadata for stateful credentials.
15
- * Extensible via TypeScript declaration merging:
16
- * declare module '@aooth/auth' {
17
- * interface CredentialMetadata { geoCountry?: string }
18
- * }
19
- */
20
- interface CredentialMetadata {
21
- ip?: string;
22
- userAgent?: string;
23
- fingerprint?: string;
24
- label?: string;
25
- }
26
- /**
27
- * Persisted state of a credential.
28
- */
29
- interface CredentialState<TClaims extends object = object> {
30
- userId: string;
31
- issuedAt: number;
32
- expiresAt: number;
33
- claims?: TClaims;
34
- metadata?: CredentialMetadata;
35
- /**
36
- * Discriminant between access and refresh credentials persisted in the same store.
37
- * Defaults to "access" when omitted.
38
- */
39
- kind?: "access" | "refresh";
40
- /** For rotated refresh tokens — id of the parent credential this one replaced */
41
- parentCredentialId?: string;
42
- /** Timestamp of rotation; used by sliding rotation grace period */
43
- rotatedAt?: number;
44
- }
45
- /**
46
- * Result of issuing a credential or refreshing it.
47
- */
48
- interface IssueResult {
49
- accessToken: string;
50
- refreshToken?: string;
51
- accessExpiresAt: number;
52
- refreshExpiresAt?: number;
53
- }
54
- /**
55
- * Refresh token configuration.
56
- */
57
- interface RefreshConfig {
58
- /** Refresh token lifetime in milliseconds. */
59
- ttl: number;
60
- /**
61
- * Rotation strategy. Defaults to 'sliding'.
62
- *
63
- * Note: 'sliding' grace-period replay tolerance only works against stateful
64
- * stores (e.g. {@link CredentialStoreMemory}). Stateless stores (JWT,
65
- * Encapsulated) cannot mutate an issued token in place; after the first
66
- * rotation the old refresh becomes unusable, so 'sliding' degrades to
67
- * 'always' semantics. Use 'always' explicitly for stateless deployments.
68
- */
69
- rotation?: "none" | "always" | "sliding";
70
- /** Grace period for sliding rotation, in milliseconds. Defaults to 30_000. */
71
- rotationGraceMs?: number;
72
- /** Theft detection hook — invoked when a previously-rotated refresh is reused. */
73
- onRotationReuse?: (state: CredentialState) => void;
74
- }
75
- //#endregion
76
- //#region src/stores/store.d.ts
77
- /**
78
- * Pluggable credential storage. Implementations: Memory, JWT, Encapsulated.
79
- * Same shape works for stateful and stateless stores. Stateless stores treat
80
- * the token as the state itself (sign/encrypt on persist, verify/decrypt on retrieve).
81
- *
82
- * `TClaims` is constrained to `extends object`, which TypeScript widens to
83
- * include arrays, class instances, and `Function`. Pass a plain object type
84
- * (e.g. `{ role: string; tenant: string }`); using arrays/classes will type-
85
- * check but won't survive JSON-serialised stateless storage round-trips.
86
- */
87
- interface CredentialStore<TClaims extends object = object> {
88
- /** Persist state, return token. For stateless stores, token IS the state. */
89
- persist(state: CredentialState<TClaims>, ttl?: number): Promise<string>;
90
- /** Retrieve state from token. Returns null if expired/invalid/revoked. */
91
- retrieve(token: string): Promise<CredentialState<TClaims> | null>;
92
- /** Retrieve + invalidate (single-use). For stateless: needs denylist. */
93
- consume(token: string): Promise<CredentialState<TClaims> | null>;
94
- /**
95
- * Update state. The returned token MAY differ from the input — stateful
96
- * stores typically return the same token, while stateless stores re-issue
97
- * a new token (denylisting the old). Callers must use the returned value.
98
- */
99
- update(token: string, state: CredentialState<TClaims>): Promise<string>;
100
- /** Revoke a single token. For stateless: requires denylist; otherwise throws. */
101
- revoke(token: string): Promise<void>;
102
- /**
103
- * Revoke all credentials for a user. Returns count revoked.
104
- * Stateless stores cannot enumerate individual tokens; they MAY implement
105
- * the cascade via a per-user revocation epoch (see `CredentialStoreJwt`)
106
- * and return a sentinel `1` to indicate "revocation took effect".
107
- */
108
- revokeAllForUser(userId: string): Promise<number>;
109
- /** List active credentials for a user (stateful only). */
110
- listForUser?(userId: string): Promise<Array<CredentialState<TClaims> & {
111
- token: string;
112
- }>>;
113
- }
114
- /**
115
- * Denylist for stateless revocation. Stores revoked-but-not-yet-expired token IDs.
116
- * Auto-bounded by token TTLs.
117
- */
118
- interface DenylistStore {
119
- add(jti: string, expiresAt: number): Promise<void>;
120
- has(jti: string): Promise<boolean>;
121
- cleanup(): Promise<number>;
122
- }
123
- //#endregion
124
- export { CredentialState as a, CredentialMetadata as i, DenylistStore as n, IssueResult as o, AuthContext as r, RefreshConfig as s, CredentialStore as t };