@kubun/store-credential 0.13.0 → 0.14.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/lib/api.d.ts CHANGED
@@ -155,5 +155,15 @@ export type CredentialStoreAPI = {
155
155
  * that is now revoked.
156
156
  */
157
157
  listHeldSubjects(): Promise<Array<HeldCredentialSubject>>;
158
+ /**
159
+ * The entry id currently pointed to by an opaque `(namespace, key)`, or
160
+ * `null` when unset. Neither argument is interpreted — a caller normalizes
161
+ * whatever it means by "key" before calling.
162
+ */
163
+ getAliasEntryID(namespace: string, key: string): Promise<string | null>;
164
+ /** Point `(namespace, key)` at `entryID`, replacing any prior target. */
165
+ setAliasEntryID(namespace: string, key: string, entryID: string): Promise<void>;
166
+ /** Clear an alias. A no-op, not an error, when none is set. */
167
+ deleteAliasEntryID(namespace: string, key: string): Promise<void>;
158
168
  };
159
169
  export declare function createCredentialStore(db: Kysely<CredentialTables>, adapter: Adapter): CredentialStoreAPI;
package/lib/api.js CHANGED
@@ -409,6 +409,25 @@ export function createCredentialStore(db, adapter) {
409
409
  subjectID: row.subject_id,
410
410
  opHash: row.op_hash
411
411
  }));
412
+ },
413
+ async getAliasEntryID (namespace, key) {
414
+ const row = await db.selectFrom('kubun_credential_aliases').select('entry_id').where('namespace', '=', namespace).where('alias_key', '=', key).executeTakeFirst();
415
+ return row?.entry_id ?? null;
416
+ },
417
+ async setAliasEntryID (namespace, key, entryID) {
418
+ await db.insertInto('kubun_credential_aliases').values({
419
+ namespace,
420
+ alias_key: key,
421
+ entry_id: entryID
422
+ }).onConflict((oc)=>oc.columns([
423
+ 'namespace',
424
+ 'alias_key'
425
+ ]).doUpdateSet({
426
+ entry_id: entryID
427
+ })).execute();
428
+ },
429
+ async deleteAliasEntryID (namespace, key) {
430
+ await db.deleteFrom('kubun_credential_aliases').where('namespace', '=', namespace).where('alias_key', '=', key).execute();
412
431
  }
413
432
  };
414
433
  }
package/lib/index.d.ts CHANGED
@@ -5,4 +5,4 @@ export { createCredentialStore } from './api.js';
5
5
  export { credentialStoreDefinition } from './definition.js';
6
6
  export declare const CREDENTIAL_STORE: "credential";
7
7
  export declare function getCredentialStore(provider: StoreProvider): Promise<CredentialStoreAPI>;
8
- export type { CredentialEntry, CredentialEntryTable, CredentialEntryWithProvenance, CredentialFactorDescriptor, CredentialKey, CredentialKeyBranch, CredentialKeyBranchTable, CredentialKeyState, CredentialKeyTable, CredentialOp, CredentialOpSubjectKind, CredentialOpTable, CredentialTables, CredentialWrapping, CredentialWrappingTable, CredentialWrappingWithBranch, InsertCredentialEntry, InsertCredentialKey, InsertCredentialOp, InsertCredentialWrapping, } from './tables.js';
8
+ export type { CredentialAlias, CredentialEntry, CredentialEntryTable, CredentialEntryWithProvenance, CredentialFactorDescriptor, CredentialKey, CredentialKeyBranch, CredentialKeyBranchTable, CredentialKeyState, CredentialKeyTable, CredentialOp, CredentialOpSubjectKind, CredentialOpTable, CredentialTables, CredentialWrapping, CredentialWrappingTable, CredentialWrappingWithBranch, InsertCredentialAlias, InsertCredentialEntry, InsertCredentialKey, InsertCredentialOp, InsertCredentialWrapping, KubunCredentialAliasTable, } from './tables.js';
package/lib/migrations.js CHANGED
@@ -42,8 +42,16 @@ export function getCredentialMigrations(ctx) {
42
42
  await db.schema.createIndex('idx_kubun_credential_ops_hlc').ifNotExists().on('kubun_credential_ops').columns([
43
43
  'hlc'
44
44
  ]).execute();
45
+ // A plain local pointer, not an op subject — no hlc, no ops row, no
46
+ // merkle scan. Devices that resolve the same (namespace, key) converge on
47
+ // it locally, so it carries nothing to replicate.
48
+ await db.schema.createTable('kubun_credential_aliases').ifNotExists().addColumn('namespace', t.text, (col)=>col.notNull()).addColumn('alias_key', t.text, (col)=>col.notNull()).addColumn('entry_id', t.text, (col)=>col.notNull()).addColumn('created_at', t.timestamp, (col)=>col.defaultTo(now).notNull()).addPrimaryKeyConstraint('pk_kubun_credential_aliases', [
49
+ 'namespace',
50
+ 'alias_key'
51
+ ]).execute();
45
52
  },
46
53
  async down (db) {
54
+ await db.schema.dropTable('kubun_credential_aliases').ifExists().execute();
47
55
  await db.schema.dropTable('kubun_credential_ops').ifExists().execute();
48
56
  await db.schema.dropTable('kubun_credential_entries').ifExists().execute();
49
57
  await db.schema.dropTable('kubun_credential_wrappings').ifExists().execute();
package/lib/tables.d.ts CHANGED
@@ -148,11 +148,30 @@ export type CredentialOpTable = {
148
148
  };
149
149
  export type CredentialOp = Selectable<CredentialOpTable>;
150
150
  export type InsertCredentialOp = Insertable<CredentialOpTable>;
151
+ /**
152
+ * A local pointer from an opaque `(namespace, key)` to the entry id it
153
+ * currently names. Not an op subject: it carries no `hlc` and never appears in
154
+ * `kubun_credential_ops` or the merkle scan, because it is a per-device index
155
+ * rather than a replicated fact — each device that resolves the same
156
+ * `(namespace, key)` points it at the entry it converges on locally.
157
+ *
158
+ * The store does not interpret `namespace`, `alias_key` or `entry_id` — they
159
+ * are stored and returned verbatim, whatever a caller passes.
160
+ */
161
+ export type KubunCredentialAliasTable = {
162
+ namespace: string;
163
+ alias_key: string;
164
+ entry_id: string;
165
+ created_at: CreatedAtColumn;
166
+ };
167
+ export type CredentialAlias = Selectable<KubunCredentialAliasTable>;
168
+ export type InsertCredentialAlias = Insertable<KubunCredentialAliasTable>;
151
169
  export type CredentialTables = {
152
170
  kubun_credential_keys: CredentialKeyTable;
153
171
  kubun_credential_key_branches: CredentialKeyBranchTable;
154
172
  kubun_credential_wrappings: CredentialWrappingTable;
155
173
  kubun_credential_entries: CredentialEntryTable;
156
174
  kubun_credential_ops: CredentialOpTable;
175
+ kubun_credential_aliases: KubunCredentialAliasTable;
157
176
  };
158
177
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/store-credential",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "keywords": [],
5
5
  "license": "see LICENSE.md",
6
6
  "sideEffects": false,
@@ -16,14 +16,14 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@kokuin/token": "^0.5.0",
19
- "kysely": "^0.29.5",
20
- "@kubun/db": "^0.13.0",
21
- "@kubun/db-adapter": "^0.13.0"
19
+ "@kubun/db": "^0.14.0",
20
+ "@kubun/db-adapter": "^0.14.0",
21
+ "kysely": "^0.29.5"
22
22
  },
23
23
  "devDependencies": {
24
- "@testcontainers/postgresql": "^12.1.0",
25
- "@kubun/db-postgres": "^0.13.0",
26
- "@kubun/db-better-sqlite": "^0.13.0"
24
+ "@kubun/db-better-sqlite": "^0.14.0",
25
+ "@kubun/db-postgres": "^0.14.0",
26
+ "@testcontainers/postgresql": "^12.1.0"
27
27
  },
28
28
  "publishConfig": {
29
29
  "access": "public"