@kubun/credential 0.17.3 → 0.18.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.
Files changed (53) hide show
  1. package/lib/api.d.ts +61 -30
  2. package/lib/api.js +455 -111
  3. package/lib/authority.d.ts +4 -0
  4. package/lib/authority.js +3 -0
  5. package/lib/branch.d.ts +4 -0
  6. package/lib/branch.js +24 -0
  7. package/lib/builder.d.ts +5 -0
  8. package/lib/builder.js +8 -6
  9. package/lib/canonical-token.d.ts +2 -0
  10. package/lib/canonical-token.js +10 -0
  11. package/lib/errors.d.ts +39 -1
  12. package/lib/errors.js +77 -0
  13. package/lib/fork-repair.d.ts +19 -0
  14. package/lib/fork-repair.js +3 -0
  15. package/lib/grantor-authority.d.ts +26 -0
  16. package/lib/grantor-authority.js +43 -0
  17. package/lib/index.d.ts +16 -6
  18. package/lib/index.js +8 -2
  19. package/lib/key-cache.d.ts +4 -3
  20. package/lib/key-cache.js +22 -15
  21. package/lib/manager-context.d.ts +50 -0
  22. package/lib/manager-context.js +82 -0
  23. package/lib/manager-entries.d.ts +3 -0
  24. package/lib/manager-entries.js +585 -0
  25. package/lib/manager-keys.d.ts +3 -0
  26. package/lib/manager-keys.js +413 -0
  27. package/lib/manager-open.d.ts +45 -0
  28. package/lib/manager-open.js +421 -0
  29. package/lib/manager-records.d.ts +94 -0
  30. package/lib/manager-records.js +291 -0
  31. package/lib/manager-removal-recovery.d.ts +7 -0
  32. package/lib/manager-removal-recovery.js +211 -0
  33. package/lib/manager-rotate.d.ts +15 -0
  34. package/lib/manager-rotate.js +536 -0
  35. package/lib/manager-types.d.ts +337 -0
  36. package/lib/manager-types.js +1 -0
  37. package/lib/manager.d.ts +2 -293
  38. package/lib/manager.js +38 -1072
  39. package/lib/manifest-token.d.ts +31 -0
  40. package/lib/manifest-token.js +51 -0
  41. package/lib/provider.d.ts +15 -2
  42. package/lib/provider.js +39 -0
  43. package/lib/record-types.d.ts +65 -0
  44. package/lib/record-types.js +865 -0
  45. package/lib/refreshing-credential-provider.d.ts +6 -2
  46. package/lib/refreshing-credential-provider.js +76 -13
  47. package/lib/suite.d.ts +5 -4
  48. package/lib/suite.js +2 -2
  49. package/lib/wrappable.d.ts +14 -0
  50. package/lib/wrappable.js +15 -0
  51. package/package.json +16 -15
  52. package/lib/op.d.ts +0 -128
  53. package/lib/op.js +0 -304
package/lib/api.d.ts CHANGED
@@ -1,16 +1,32 @@
1
1
  import { type MethodRegistry } from '@kokuin/token';
2
+ import type { AdoptGrantParams, AdoptGrantResult } from '@kubun/credential-types';
2
3
  import type { StoreProvider } from '@kubun/db';
3
4
  import type { Logger } from '@kubun/logger';
4
5
  import type { CredentialManager } from './manager.js';
5
6
  /**
6
- * The credential seam: resolves its `(providerName, ownerDID) → entryID` pointer
7
+ * The credential seam: resolves its `(providerName, ownerDID, deviceDID) → entryID` pointer
7
8
  * through the alias layer of the credential store, and its entries through a
8
9
  * `CredentialManager`. Every `ownerDID` is normalized before it reaches the
9
10
  * alias, so an un-normalized equality key cannot split one account across two
10
11
  * rows: a credential invisible under one spelling and un-revokable under the
11
12
  * other.
12
13
  */
14
+ export type CreateCredentialParams = {
15
+ providerName: string;
16
+ ownerDID: string;
17
+ ownerWrappableDID: string;
18
+ controllerWrappableDID?: string;
19
+ credential: string;
20
+ /** Service authority check before replacing an existing grant. */
21
+ authorizeKeyOwnerDID?: (ownerDID: string) => Promise<boolean>;
22
+ };
23
+ export type AdoptGrantRecoveryParams = AdoptGrantParams & {
24
+ sourceKeyOwnerDID?: string;
25
+ };
13
26
  export type CredentialAPI = {
27
+ getLocalDeviceDID: () => string;
28
+ getGrantKeyOwnerDID: (params: AdoptGrantRecoveryParams) => Promise<string>;
29
+ adoptCredentialGrant: (params: AdoptGrantRecoveryParams, authorizedKeyOwnerDID?: string) => Promise<AdoptGrantResult>;
14
30
  getCredential: (providerName: string, ownerDID: string) => Promise<string | null>;
15
31
  getCredentialProvenance: (providerName: string, ownerDID: string) => Promise<{
16
32
  updatedAt: string | null;
@@ -29,21 +45,15 @@ export type CredentialAPI = {
29
45
  * with no owner in hand would mint one wrapped to the server alone — locking
30
46
  * the account owner out of their own credential with nothing failing.
31
47
  */
32
- createCredential: (params: {
33
- providerName: string;
34
- ownerDID: string;
35
- ownerWrappableDID: string;
36
- controllerWrappableDID?: string;
37
- credential: string;
38
- }) => Promise<void>;
48
+ createCredential: (params: CreateCredentialParams) => Promise<void>;
39
49
  deleteCredential: (providerName: string, ownerDID: string) => Promise<void>;
40
50
  /**
41
- * Point `(providerName, ownerDID)` at an entry this device already holds,
51
+ * Point this device's `(providerName, ownerDID, deviceDID)` alias at an entry it holds,
42
52
  * without minting anything.
43
53
  *
44
- * Gate B first: the entry's key must be owned by `ownerDID` (normalized on
45
- * both sides), because the vault can decrypt any entry it holds a server
46
- * wrapping for — decryptability is not authority. An idempotent retry that
54
+ * Gate B first: the signed grant and its key must name `ownerDID`. The vault
55
+ * can decrypt entries it holds a server wrapping for — decryptability is not authority.
56
+ * An idempotent retry that
47
57
  * already points at `entryID` returns before that entry is ever decrypted, so
48
58
  * a safe retry cannot fail on a branch/version check inside the read. Only
49
59
  * then is the decrypted plaintext checked against the `Credential` shape, so a
@@ -53,18 +63,14 @@ export type CredentialAPI = {
53
63
  /**
54
64
  * The normalized owner DIDs that currently hold a credential for `providerName`.
55
65
  *
56
- * A credential is pointed at by an alias keyed `(providerName, normalizeDID(
57
- * ownerDID))`, so the alias keys under a provider namespace are exactly its
58
- * authenticated owners — already normalized, so a caller can key sync state or
59
- * a schedule on them directly. Empty when no owner holds one.
66
+ * A credential is pointed at by an alias keyed by provider, normalized owner,
67
+ * and the local identity's DID. The owners under a provider namespace are
68
+ * already normalized, so a caller can key sync state on them directly.
60
69
  */
61
70
  listSubjects: (providerName: string) => Promise<Array<string>>;
62
71
  /**
63
- * The controller resolvers for this API's (request-scoped) transaction
64
- * provider — the exact `methods` the credential mint passes to `createKey`.
65
- * Exposed so the OAuth pre-flight can ask `canWrapTo` with the same resolver
66
- * the mint uses, rather than failing closed on a `did:kokuin:` owner whose
67
- * agreement key is resolvable only through the controller resolver.
72
+ * Pull-capable controller resolvers for OAuth pre-flight `canWrapTo`.
73
+ * Minting uses their local-only counterparts after recipients are prewarmed.
68
74
  */
69
75
  getControllerMethods: () => MethodRegistry;
70
76
  /**
@@ -87,6 +93,29 @@ export type CredentialAPI = {
87
93
  entryID: string;
88
94
  credential: string;
89
95
  }) => Promise<'updated' | 'absent'>;
96
+ /**
97
+ * As `getCredentialRef`, plus the entry's `version`: an opaque token that
98
+ * changes on every write to the entry, read before the credential itself so it
99
+ * is never newer than the credential returned with it.
100
+ */
101
+ getVersionedCredentialRef: (providerName: string, ownerDID: string) => Promise<{
102
+ credential: string;
103
+ entryID: string;
104
+ version: string;
105
+ } | null>;
106
+ /**
107
+ * As `setCredentialForEntry`, and also only while the entry is still at
108
+ * `expectedVersion` (from `getVersionedCredentialRef`). A write that landed in
109
+ * between is kept and reported as `'superseded'`; the check and the write are
110
+ * one atomic store call inside whatever transaction the API runs in.
111
+ */
112
+ setCredentialForEntryIfUnchanged: (params: {
113
+ providerName: string;
114
+ ownerDID: string;
115
+ entryID: string;
116
+ credential: string;
117
+ expectedVersion: string;
118
+ }) => Promise<'updated' | 'absent' | 'superseded'>;
90
119
  };
91
120
  export type CreateCredentialAPIParams = {
92
121
  stores: StoreProvider;
@@ -96,16 +125,18 @@ export type CreateCredentialAPIParams = {
96
125
  * that provider is the transaction and a manager built over the base one
97
126
  * would read outside it.
98
127
  */
99
- getCredentialManager: (stores: StoreProvider) => Promise<CredentialManager>;
128
+ getCredentialManager: (stores: StoreProvider, recoveryChecked?: boolean) => Promise<CredentialManager>;
100
129
  /** The engine's own DID, in a form that can be encrypted to. */
101
130
  serverWrappableDID: string;
102
- /**
103
- * Resolvers for wrapping recipients that carry no key material of their own
104
- * (`did:kokuin:`), scoped to the request's transaction provider so a resolve
105
- * reads the mutation's tx, never a second connection. A self-contained
106
- * recipient resolves with an empty registry, so callers with no controller
107
- * recipient in play still pass `() => []`.
108
- */
109
- getControllerMethods: (stores: StoreProvider) => MethodRegistry;
131
+ /** Resolvers for controller recipients; minting must use local-only methods. */
132
+ getControllerMethods: (stores: StoreProvider, options?: {
133
+ localOnly?: boolean;
134
+ }) => MethodRegistry;
135
+ /** The caller already resolved recipients before opening its ambient transaction. */
136
+ wrappingRecipientsPrewarmed?: boolean;
137
+ /** The current controller of an account device, if one is locally verifiable. */
138
+ resolveControllerOfOwner?: (ownerDID: string, stores: StoreProvider) => Promise<string | null>;
139
+ /** Authority used by local providers before replacing an existing grant. */
140
+ authorizeKeyOwnerDID?: (ownerDID: string, stores: StoreProvider) => Promise<boolean>;
110
141
  };
111
142
  export declare function createCredentialAPI(params: CreateCredentialAPIParams): CredentialAPI;