@dsh-enhanced/credentials-keychain 0.1.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-enhanced contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # @dsh-enhanced/credentials-keychain
2
+
3
+ 给可信 DSH 插件使用的凭据 handle 服务。配置只保存 locator 与 allowlist,值留在 macOS Keychain、Linux Secret Service、当前 Windows 用户的 DPAPI 加密文件或一个明确命名的进程环境变量中;每次使用都经过 `assistant-policy`、有界 lease 和不含 secret 的 SQLite 审计账本。
4
+
5
+ 它不是密码管理器 UI,也不向 Agent 注册任何 tool。
6
+
7
+ ## 安装
8
+
9
+ 先安装 `@dsh-enhanced/assistant-policy`,再安装:
10
+
11
+ ```sh
12
+ dsh plugin --profile web add @dsh-enhanced/credentials-keychain
13
+ dsh --profile web --dump-config
14
+ ```
15
+
16
+ 默认 `handles: []`,不会读取任何凭据。示例:
17
+
18
+ ```yaml
19
+ handles:
20
+ - id: lark-app-secret
21
+ provider: macos-keychain
22
+ service: dsh/lark
23
+ account: personal
24
+ consumers: [dsh-enhanced-lark-channel]
25
+ purposes: [connect]
26
+ maxLeaseMs: 86400000
27
+ ```
28
+
29
+ 相应 policy rule 必须显式允许:
30
+
31
+ ```yaml
32
+ - id: lark-credential
33
+ effect: allow
34
+ subject: { kind: background, id: dsh-enhanced-lark-channel }
35
+ actions: [credential.use]
36
+ resource: { kind: credential, id: lark-app-secret }
37
+ context: { initiators: [background] }
38
+ ```
39
+
40
+ 本地运维撤销还需单独允许 `external/local:<operator>` 的 `credential.revoke`。
41
+
42
+ ## Provider
43
+
44
+ ### macOS Keychain
45
+
46
+ 插件只执行固定命令:
47
+
48
+ ```text
49
+ /usr/bin/security find-generic-password -w -s <service> -a <account>
50
+ ```
51
+
52
+ 先由用户在系统外部写入 Keychain;本插件 v0.1 不创建、修改或删除条目。
53
+
54
+ ### Linux Secret Service
55
+
56
+ 插件只执行:
57
+
58
+ ```text
59
+ /usr/bin/secret-tool lookup service <service> account <account>
60
+ ```
61
+
62
+ 子进程只收到固定 `PATH`,以及宿主已有的 `DBUS_SESSION_BUS_ADDRESS` / `XDG_RUNTIME_DIR`。不继承 `HOME`、token、代理或完整环境。
63
+
64
+ ### Environment
65
+
66
+ ```yaml
67
+ - id: lark-app-secret
68
+ provider: environment
69
+ environmentName: LARK_APP_SECRET
70
+ consumers: [dsh-enhanced-lark-channel]
71
+ purposes: [connect]
72
+ maxLeaseMs: 86400000
73
+ ```
74
+
75
+ 只读取这一项;其他环境值不会复制给 consumer。该 provider 适合由 launchd/systemd/container secret injection 管理的部署,安全性取决于进程启动环境。
76
+
77
+ ### Windows DPAPI(best-effort)
78
+
79
+ ```yaml
80
+ - id: lark-app-secret
81
+ provider: windows-dpapi
82
+ path: 'C:\Users\me\.dsh\credentials-keychain\lark-web-primary.clixml'
83
+ consumers: [dsh-enhanced-lark-channel]
84
+ purposes: [connect]
85
+ maxLeaseMs: 86400000
86
+ ```
87
+
88
+ 插件只执行固定的 Windows PowerShell `Import-Clixml` 解密命令,文件路径作为单独 argv 传入,PowerShell 脚本内容和可执行文件不能由配置覆盖。文件由 `dsh-lark-setup` 使用当前用户 DPAPI 创建,只能由同一 Windows 用户在同一登录上下文解密。Windows 路径已实现但不作跨 Windows/PowerShell/npm 组合的兼容承诺。
89
+
90
+ ## Lease 语义
91
+
92
+ - consumer id 从调用方 Cordis fiber 的插件 `name` 推导,不能由 request 字符串指定。
93
+ - handle 同时校验 consumer、purpose、TTL 上限和 `assistant-policy`;任一未知值默认拒绝。
94
+ - `withSecret(caller, request, callback)` 只在 callback 期间传值,并提供 AbortSignal。完成、provider 失败、TTL、运维撤销和服务卸载都会写入 lease/audit ledger。
95
+ - idempotency key 只执行一次;已完成/失败/过期请求不会再次调用 callback。
96
+ - 运维撤销只中断精确 lease,不自动删除 OS 凭据。
97
+ - JavaScript string 无法可靠清零;consumer 必须不缓存、不记录、不返回 secret,并在 AbortSignal 后立即释放持有 secret 的 SDK/连接。
98
+
99
+ ## 权限与数据
100
+
101
+ - **文件系统:**创建配置指定的绝对 SQLite 文件;父目录 `0700`、文件 `0600`、WAL/FULL、forward-only migration。账本只存 handle id、consumer、purpose、状态和时间,不存 locator 或值。
102
+ - **子进程:**仅 OS provider 的固定可执行文件与固定 argv 结构(macOS `security`、Linux `secret-tool`、Windows PowerShell DPAPI);`shell: false`,5 秒默认超时,stdout/stderr 总量有界,错误文本不回传。
103
+ - **环境:**environment provider 读取单个 allowlisted 名称;Linux provider只转交 D-Bus/XDG session 定位。
104
+ - **网络:**无。
105
+ - **浏览器:**无。
106
+ - **凭据:**值只进入可信 consumer callback。`health`、`listHandles`、`listLeases`、异常与 policy audit 均不含值。
107
+ - **安装脚本:**无。
108
+
109
+ Cordis fiber identity 与 callback 是同进程合作式边界,不能阻止恶意插件通过 Node API 自行读环境、文件或其他进程。强隔离需要独立进程/容器和宿主 capability sandbox;本包不作虚假承诺。
110
+
111
+ ## 兼容性
112
+
113
+ - `@deepseek-ai/cordis ^4.0.1`
114
+ - `@dsh-enhanced/assistant-policy >=0.1.0 <0.2.0`
115
+ - Node.js `^22.19.0 || >=24.0.0`(使用 `node:sqlite`)
116
+
117
+ 参见仓库的[兼容性基线](../../docs/compatibility.md)。
@@ -0,0 +1,11 @@
1
+ - insert:
2
+ - id: dsh-enhanced-credentials-keychain
3
+ name: '@dsh-enhanced/credentials-keychain'
4
+ inject:
5
+ - assistantPolicy
6
+ config:
7
+ databasePath: !!js dshHomePath('credentials-keychain/ledger.sqlite')
8
+ defaultLeaseMs: 300000
9
+ maxSecretBytes: 65536
10
+ providerTimeoutMs: 5000
11
+ handles: []
@@ -0,0 +1,12 @@
1
+ import Schema from '@deepseek-ai/schemastery';
2
+ import type { CredentialHandle } from './types.js';
3
+ export interface Config {
4
+ databasePath: string;
5
+ handles: CredentialHandle[];
6
+ defaultLeaseMs?: number;
7
+ maxSecretBytes?: number;
8
+ providerTimeoutMs?: number;
9
+ }
10
+ export declare function normalizeHandles(input: readonly CredentialHandle[]): CredentialHandle[];
11
+ export declare const Config: Schema<Config>;
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAE7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,MAAM,WAAW,MAAM;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAgDD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAkCvF;AAwBD,eAAO,MAAM,MAAM,EAYb,MAAM,CAAC,MAAM,CAAC,CAAA"}
package/lib/config.js ADDED
@@ -0,0 +1,115 @@
1
+ import Schema from '@deepseek-ai/schemastery';
2
+ import { isAbsolute, win32 } from 'node:path';
3
+ const keyPattern = /^[A-Za-z0-9][A-Za-z0-9._@/-]{0,127}$/u;
4
+ const envPattern = /^[A-Z_][A-Z0-9_]*$/u;
5
+ function exact(value, fields) {
6
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
7
+ throw new Error('credentials-keychain: handle must be an object');
8
+ }
9
+ const record = value;
10
+ const unknown = Object.keys(record).find(field => !fields.includes(field));
11
+ if (unknown !== undefined)
12
+ throw new Error(`credentials-keychain: unknown handle field: ${unknown}`);
13
+ return record;
14
+ }
15
+ function key(value, field) {
16
+ if (typeof value !== 'string' || !keyPattern.test(value)) {
17
+ throw new Error(`credentials-keychain: invalid ${field}`);
18
+ }
19
+ return value;
20
+ }
21
+ function strings(value, field) {
22
+ if (!Array.isArray(value) || value.length < 1 || value.length > 32) {
23
+ throw new Error(`credentials-keychain: ${field} allowlist must contain 1..32 values`);
24
+ }
25
+ const normalized = value.map(entry => key(entry, field));
26
+ if (new Set(normalized).size !== normalized.length) {
27
+ throw new Error(`credentials-keychain: duplicate ${field}`);
28
+ }
29
+ return normalized;
30
+ }
31
+ function lease(value) {
32
+ if (!Number.isSafeInteger(value) || value < 1_000 || value > 86_400_000) {
33
+ throw new Error('credentials-keychain: maxLeaseMs must be an integer from 1000 to 86400000');
34
+ }
35
+ return value;
36
+ }
37
+ function credentialPath(value) {
38
+ if (typeof value !== 'string' || value.length < 1 || value.length > 1_024 || value.includes('\0')
39
+ || (!isAbsolute(value) && !win32.isAbsolute(value))) {
40
+ throw new Error('credentials-keychain: invalid path');
41
+ }
42
+ return value;
43
+ }
44
+ export function normalizeHandles(input) {
45
+ if (!Array.isArray(input) || input.length > 256)
46
+ throw new Error('credentials-keychain: handles must contain at most 256 values');
47
+ const identifiers = new Set();
48
+ return input.map(raw => {
49
+ const discriminator = exact(raw, [
50
+ 'account', 'consumers', 'environmentName', 'id', 'maxLeaseMs', 'path', 'provider', 'purposes', 'service',
51
+ ]);
52
+ const id = key(discriminator.id, 'id');
53
+ if (identifiers.has(id))
54
+ throw new Error(`credentials-keychain: duplicate handle id: ${id}`);
55
+ identifiers.add(id);
56
+ const common = {
57
+ id,
58
+ consumers: strings(discriminator.consumers, 'consumer'),
59
+ purposes: strings(discriminator.purposes, 'purpose'),
60
+ maxLeaseMs: lease(discriminator.maxLeaseMs),
61
+ };
62
+ if (discriminator.provider === 'environment') {
63
+ const value = exact(raw, ['consumers', 'environmentName', 'id', 'maxLeaseMs', 'provider', 'purposes']);
64
+ if (typeof value.environmentName !== 'string' || !envPattern.test(value.environmentName)) {
65
+ throw new Error('credentials-keychain: invalid environmentName');
66
+ }
67
+ return { ...common, provider: 'environment', environmentName: value.environmentName };
68
+ }
69
+ if (discriminator.provider === 'macos-keychain' || discriminator.provider === 'linux-secret-service') {
70
+ const value = exact(raw, ['account', 'consumers', 'id', 'maxLeaseMs', 'provider', 'purposes', 'service']);
71
+ return { ...common, provider: discriminator.provider,
72
+ service: key(value.service, 'service'), account: key(value.account, 'account') };
73
+ }
74
+ if (discriminator.provider === 'windows-dpapi') {
75
+ const value = exact(raw, ['consumers', 'id', 'maxLeaseMs', 'path', 'provider', 'purposes']);
76
+ return { ...common, provider: discriminator.provider, path: credentialPath(value.path) };
77
+ }
78
+ throw new Error('credentials-keychain: unsupported provider');
79
+ });
80
+ }
81
+ const handleSchema = Schema.object({
82
+ id: Schema.string().required(),
83
+ provider: Schema.union(['environment', 'linux-secret-service', 'macos-keychain', 'windows-dpapi']).required(),
84
+ environmentName: Schema.string(),
85
+ service: Schema.string(),
86
+ account: Schema.string(),
87
+ path: Schema.string(),
88
+ consumers: Schema.array(Schema.string()).required(),
89
+ purposes: Schema.array(Schema.string()).required(),
90
+ maxLeaseMs: Schema.number().required(),
91
+ });
92
+ const schema = Schema.object({
93
+ databasePath: Schema.string().required(),
94
+ handles: Schema.array(handleSchema).default([]),
95
+ defaultLeaseMs: Schema.number().step(1).min(1_000).max(86_400_000).default(300_000),
96
+ maxSecretBytes: Schema.number().step(1).min(1).max(1024 * 1024).default(65_536),
97
+ providerTimeoutMs: Schema.number().step(1).min(100).max(60_000).default(5_000),
98
+ });
99
+ const configFields = new Set(['databasePath', 'defaultLeaseMs', 'handles', 'maxSecretBytes', 'providerTimeoutMs']);
100
+ export const Config = new Proxy(schema, {
101
+ apply(target, thisArg, argumentsList) {
102
+ const input = argumentsList[0];
103
+ if (input !== null && typeof input === 'object' && !Array.isArray(input)) {
104
+ const record = input;
105
+ const unknown = Object.keys(record).find(field => !configFields.has(field));
106
+ if (unknown !== undefined)
107
+ throw new Error(`credentials-keychain: unknown config field: ${unknown}`);
108
+ if (record.handles !== undefined)
109
+ normalizeHandles(record.handles);
110
+ }
111
+ const parsed = Reflect.apply(target, thisArg, argumentsList);
112
+ return { ...parsed, handles: normalizeHandles(parsed.handles) };
113
+ },
114
+ });
115
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import { Config } from './config.js';
3
+ import { CredentialLeaseAbortError, CredentialsKeychainService } from './service.js';
4
+ import { version } from './version.js';
5
+ export declare const name = "dsh-enhanced-credentials-keychain";
6
+ export declare const inject: string[];
7
+ export { Config, CredentialLeaseAbortError, CredentialsKeychainService, version };
8
+ export type { CredentialLeaseAbortCode } from './service.js';
9
+ export * from './types.js';
10
+ export declare function apply(ctx: Context, config: import('./config.js').Config): void;
11
+ export default CredentialsKeychainService;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,eAAO,MAAM,IAAI,sCAAsC,CAAA;AACvD,eAAO,MAAM,MAAM,UAAsB,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,OAAO,EAAE,CAAA;AACjF,YAAY,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAC5D,cAAc,YAAY,CAAA;AAE1B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,aAAa,EAAE,MAAM,GAAG,IAAI,CAE9E;AAED,eAAe,0BAA0B,CAAA"}
package/lib/index.js ADDED
@@ -0,0 +1,12 @@
1
+ import { Config } from './config.js';
2
+ import { CredentialLeaseAbortError, CredentialsKeychainService } from './service.js';
3
+ import { version } from './version.js';
4
+ export const name = 'dsh-enhanced-credentials-keychain';
5
+ export const inject = ['assistantPolicy'];
6
+ export { Config, CredentialLeaseAbortError, CredentialsKeychainService, version };
7
+ export * from './types.js';
8
+ export function apply(ctx, config) {
9
+ new CredentialsKeychainService(ctx, config);
10
+ }
11
+ export default CredentialsKeychainService;
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,IAAI,GAAG,mCAAmC,CAAA;AACvD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,iBAAiB,CAAC,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,OAAO,EAAE,CAAA;AAEjF,cAAc,YAAY,CAAA;AAE1B,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAAoC;IACtE,IAAI,0BAA0B,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;AAC7C,CAAC;AAED,eAAe,0BAA0B,CAAA"}
@@ -0,0 +1,60 @@
1
+ import type { CredentialLeaseRecord, CredentialLeaseStatus } from './types.js';
2
+ export type CredentialLedgerErrorCode = 'idempotency-conflict' | 'invalid-input' | 'invalid-path' | 'invalid-state' | 'not-found' | 'schema-too-new' | 'version-conflict';
3
+ export declare class CredentialLedgerError extends Error {
4
+ readonly code: CredentialLedgerErrorCode;
5
+ constructor(code: CredentialLedgerErrorCode, message: string);
6
+ }
7
+ export interface CredentialLedgerOptions {
8
+ path: string;
9
+ now?: () => number;
10
+ }
11
+ export interface CredentialAuditRecord {
12
+ sequence: number;
13
+ occurredAt: number;
14
+ action: string;
15
+ leaseId: string;
16
+ handleId: string;
17
+ consumer: string;
18
+ purpose: string;
19
+ outcome: string;
20
+ failureCode?: string;
21
+ actor?: string;
22
+ reason?: string;
23
+ }
24
+ export declare class CredentialLedger {
25
+ #private;
26
+ constructor(options: CredentialLedgerOptions);
27
+ close(): void;
28
+ begin(input: {
29
+ handleId: string;
30
+ consumer: string;
31
+ purpose: string;
32
+ idempotencyKey: string;
33
+ ttlMs: number;
34
+ }): {
35
+ record: CredentialLeaseRecord;
36
+ replayed: boolean;
37
+ };
38
+ get(id: string): CredentialLeaseRecord | undefined;
39
+ settle(input: {
40
+ leaseId: string;
41
+ expectedVersion: number;
42
+ status: 'completed' | 'expired' | 'failed';
43
+ failureCode?: string;
44
+ }): CredentialLeaseRecord;
45
+ revoke(input: {
46
+ leaseId: string;
47
+ expectedVersion: number;
48
+ actor: string;
49
+ reason: string;
50
+ }): CredentialLeaseRecord;
51
+ expire(): number;
52
+ list(input?: {
53
+ status?: CredentialLeaseStatus;
54
+ limit?: number;
55
+ }): CredentialLeaseRecord[];
56
+ listAudit(input?: {
57
+ limit?: number;
58
+ }): CredentialAuditRecord[];
59
+ }
60
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAE9E,MAAM,MAAM,yBAAyB,GACjC,sBAAsB,GACtB,eAAe,GACf,cAAc,GACd,eAAe,GACf,WAAW,GACX,gBAAgB,GAChB,kBAAkB,CAAA;AAEtB,qBAAa,qBAAsB,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,yBAAyB;gBAA/B,IAAI,EAAE,yBAAyB,EAAE,OAAO,EAAE,MAAM;CAItE;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAoDD,qBAAa,gBAAgB;;gBAKf,OAAO,EAAE,uBAAuB;IAU5C,KAAK,IAAI,IAAI;IAMb,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,MAAM,CAAA;QAChB,OAAO,EAAE,MAAM,CAAA;QACf,cAAc,EAAE,MAAM,CAAA;QACtB,KAAK,EAAE,MAAM,CAAA;KACd,GAAG;QAAE,MAAM,EAAE,qBAAqB,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE;IAsCxD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAKlD,MAAM,CAAC,KAAK,EAAE;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,eAAe,EAAE,MAAM,CAAA;QACvB,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;QAC1C,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,GAAG,qBAAqB;IAYzB,MAAM,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,qBAAqB;IAajH,MAAM,IAAI,MAAM;IAWhB,IAAI,CAAC,KAAK,GAAE;QAAE,MAAM,CAAC,EAAE,qBAAqB,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,qBAAqB,EAAE;IAS7F,SAAS,CAAC,KAAK,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,qBAAqB,EAAE;CAiEnE"}
package/lib/ledger.js ADDED
@@ -0,0 +1,194 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { CredentialDatabaseError, openCredentialDatabase } from './sqlite.js';
3
+ export class CredentialLedgerError extends Error {
4
+ code;
5
+ constructor(code, message) {
6
+ super(message);
7
+ this.code = code;
8
+ this.name = 'CredentialLedgerError';
9
+ }
10
+ }
11
+ function text(value, field) {
12
+ if (value.trim().length === 0 || value.length > 256) {
13
+ throw new CredentialLedgerError('invalid-input', `${field} must contain 1..256 characters`);
14
+ }
15
+ }
16
+ function record(row) {
17
+ return {
18
+ id: row.id,
19
+ handleId: row.handle_id,
20
+ consumer: row.consumer,
21
+ purpose: row.purpose,
22
+ idempotencyKey: row.idempotency_key,
23
+ status: row.status,
24
+ issuedAt: row.issued_at,
25
+ expiresAt: row.expires_at,
26
+ ...(row.settled_at === null ? {} : { settledAt: row.settled_at }),
27
+ ...(row.failure_code === null ? {} : { failureCode: row.failure_code }),
28
+ version: row.version,
29
+ };
30
+ }
31
+ export class CredentialLedger {
32
+ #database;
33
+ #now;
34
+ #closed = false;
35
+ constructor(options) {
36
+ this.#now = options.now ?? Date.now;
37
+ try {
38
+ this.#database = openCredentialDatabase(options.path);
39
+ }
40
+ catch (error) {
41
+ if (error instanceof CredentialDatabaseError)
42
+ throw new CredentialLedgerError(error.code, error.message);
43
+ throw error;
44
+ }
45
+ }
46
+ close() {
47
+ if (this.#closed)
48
+ return;
49
+ this.#closed = true;
50
+ this.#database.close();
51
+ }
52
+ begin(input) {
53
+ text(input.handleId, 'handleId');
54
+ text(input.consumer, 'consumer');
55
+ text(input.purpose, 'purpose');
56
+ text(input.idempotencyKey, 'idempotencyKey');
57
+ if (!Number.isSafeInteger(input.ttlMs) || input.ttlMs <= 0) {
58
+ throw new CredentialLedgerError('invalid-input', 'ttlMs must be a positive safe integer');
59
+ }
60
+ const now = this.#now();
61
+ return this.#transaction(() => {
62
+ const existing = this.#byIdempotency(input.idempotencyKey);
63
+ if (existing !== undefined) {
64
+ if (existing.handle_id !== input.handleId || existing.consumer !== input.consumer
65
+ || existing.purpose !== input.purpose || existing.expires_at - existing.issued_at !== input.ttlMs) {
66
+ throw new CredentialLedgerError('idempotency-conflict', 'idempotency key belongs to another lease request');
67
+ }
68
+ if (existing.status === 'active' && existing.expires_at <= now) {
69
+ const expired = this.#settleRow(existing, 'expired', 'lease-expired', now);
70
+ return { record: record(expired), replayed: true };
71
+ }
72
+ return { record: record(existing), replayed: true };
73
+ }
74
+ const row = {
75
+ id: randomUUID(), idempotency_key: input.idempotencyKey, handle_id: input.handleId,
76
+ consumer: input.consumer, purpose: input.purpose, status: 'active', issued_at: now,
77
+ expires_at: now + input.ttlMs, settled_at: null, failure_code: null, version: 1,
78
+ };
79
+ this.#database.prepare(`
80
+ INSERT INTO credential_leases(
81
+ id, idempotency_key, handle_id, consumer, purpose, status, issued_at, expires_at,
82
+ settled_at, failure_code, version
83
+ ) VALUES (?, ?, ?, ?, ?, 'active', ?, ?, NULL, NULL, 1)
84
+ `).run(row.id, row.idempotency_key, row.handle_id, row.consumer, row.purpose, row.issued_at, row.expires_at);
85
+ this.#audit(row, 'lease.begin', 'active');
86
+ return { record: record(row), replayed: false };
87
+ });
88
+ }
89
+ get(id) {
90
+ const row = this.#row(id);
91
+ return row === undefined ? undefined : record(row);
92
+ }
93
+ settle(input) {
94
+ return this.#transaction(() => {
95
+ const row = this.#required(input.leaseId);
96
+ if (row.version !== input.expectedVersion)
97
+ throw new CredentialLedgerError('version-conflict', 'lease version changed');
98
+ if (row.status !== 'active') {
99
+ if (row.status === input.status)
100
+ return record(row);
101
+ throw new CredentialLedgerError('invalid-state', `cannot settle a ${row.status} lease`);
102
+ }
103
+ return record(this.#settleRow(row, input.status, input.failureCode ?? null, this.#now()));
104
+ });
105
+ }
106
+ revoke(input) {
107
+ text(input.actor, 'actor');
108
+ text(input.reason, 'reason');
109
+ return this.#transaction(() => {
110
+ const row = this.#required(input.leaseId);
111
+ if (row.version !== input.expectedVersion)
112
+ throw new CredentialLedgerError('version-conflict', 'lease version changed');
113
+ if (row.status === 'revoked')
114
+ return record(row);
115
+ if (row.status !== 'active')
116
+ throw new CredentialLedgerError('invalid-state', `cannot revoke a ${row.status} lease`);
117
+ const revoked = this.#settleRow(row, 'revoked', 'operator-revoked', this.#now(), input.actor, input.reason);
118
+ return record(revoked);
119
+ });
120
+ }
121
+ expire() {
122
+ const now = this.#now();
123
+ return this.#transaction(() => {
124
+ const rows = this.#database.prepare(`
125
+ SELECT * FROM credential_leases WHERE status = 'active' AND expires_at <= ? ORDER BY id
126
+ `).all(now);
127
+ for (const row of rows)
128
+ this.#settleRow(row, 'expired', 'lease-expired', now);
129
+ return rows.length;
130
+ });
131
+ }
132
+ list(input = {}) {
133
+ const limit = Math.min(Math.max(input.limit ?? 100, 1), 1_000);
134
+ const rows = input.status === undefined
135
+ ? this.#database.prepare('SELECT * FROM credential_leases ORDER BY issued_at DESC, id DESC LIMIT ?').all(limit)
136
+ : this.#database.prepare('SELECT * FROM credential_leases WHERE status = ? ORDER BY issued_at DESC, id DESC LIMIT ?')
137
+ .all(input.status, limit);
138
+ return rows.map(record);
139
+ }
140
+ listAudit(input = {}) {
141
+ const limit = Math.min(Math.max(input.limit ?? 100, 1), 1_000);
142
+ const rows = this.#database.prepare('SELECT * FROM credential_audit ORDER BY sequence DESC LIMIT ?')
143
+ .all(limit);
144
+ return rows.map(row => ({
145
+ sequence: row.sequence, occurredAt: row.occurred_at, action: row.action, leaseId: row.lease_id,
146
+ handleId: row.handle_id, consumer: row.consumer, purpose: row.purpose, outcome: row.outcome,
147
+ ...(row.failure_code === null ? {} : { failureCode: row.failure_code }),
148
+ ...(row.actor === null ? {} : { actor: row.actor }),
149
+ ...(row.reason === null ? {} : { reason: row.reason }),
150
+ }));
151
+ }
152
+ #transaction(operation) {
153
+ this.#database.exec('BEGIN IMMEDIATE');
154
+ try {
155
+ const value = operation();
156
+ this.#database.exec('COMMIT');
157
+ return value;
158
+ }
159
+ catch (error) {
160
+ this.#database.exec('ROLLBACK');
161
+ throw error;
162
+ }
163
+ }
164
+ #row(id) {
165
+ return this.#database.prepare('SELECT * FROM credential_leases WHERE id = ?').get(id);
166
+ }
167
+ #required(id) {
168
+ const row = this.#row(id);
169
+ if (row === undefined)
170
+ throw new CredentialLedgerError('not-found', 'credential lease does not exist');
171
+ return row;
172
+ }
173
+ #byIdempotency(key) {
174
+ return this.#database.prepare('SELECT * FROM credential_leases WHERE idempotency_key = ?').get(key);
175
+ }
176
+ #settleRow(row, status, failureCode, now, actor, reason) {
177
+ this.#database.prepare(`
178
+ UPDATE credential_leases
179
+ SET status = ?, settled_at = ?, failure_code = ?, version = version + 1
180
+ WHERE id = ? AND version = ? AND status = 'active'
181
+ `).run(status, now, failureCode, row.id, row.version);
182
+ const updated = { ...row, status, settled_at: now, failure_code: failureCode, version: row.version + 1 };
183
+ this.#audit(updated, `lease.${status}`, status, actor, reason);
184
+ return updated;
185
+ }
186
+ #audit(row, action, outcome, actor, reason) {
187
+ this.#database.prepare(`
188
+ INSERT INTO credential_audit(
189
+ occurred_at, action, lease_id, handle_id, consumer, purpose, outcome, failure_code, actor, reason
190
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
191
+ `).run(this.#now(), action, row.id, row.handle_id, row.consumer, row.purpose, outcome, row.failure_code, actor ?? null, reason ?? null);
192
+ }
193
+ }
194
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { CredentialCommandRunner, CredentialHandle, CredentialProviderErrorCode } from './types.js';
2
+ export declare class CredentialProviderError extends Error {
3
+ readonly code: CredentialProviderErrorCode;
4
+ constructor(code: CredentialProviderErrorCode, message: string);
5
+ }
6
+ export interface ReadCredentialOptions {
7
+ env: Readonly<Record<string, string | undefined>>;
8
+ run: CredentialCommandRunner;
9
+ timeoutMs: number;
10
+ maxSecretBytes: number;
11
+ }
12
+ export declare function readCredential(handle: CredentialHandle, options: ReadCredentialOptions): Promise<string>;
13
+ export declare const runCredentialCommand: CredentialCommandRunner;
14
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,uBAAuB,EACvB,gBAAgB,EAChB,2BAA2B,EAC5B,MAAM,YAAY,CAAA;AAEnB,qBAAa,uBAAwB,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,2BAA2B;gBAAjC,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,MAAM;CAIxE;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IACjD,GAAG,EAAE,uBAAuB,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;CACvB;AAsBD,wBAAsB,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CA8C9G;AAED,eAAO,MAAM,oBAAoB,EAAE,uBAyCjC,CAAA"}