@centient/secrets 0.10.0 → 0.11.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/README.md +355 -7
- package/dist/audit/hmac-chain.d.ts +117 -0
- package/dist/audit/hmac-chain.d.ts.map +1 -0
- package/dist/audit/hmac-chain.js +811 -0
- package/dist/audit/hmac-chain.js.map +1 -0
- package/dist/audit/ocsf.d.ts +108 -0
- package/dist/audit/ocsf.d.ts.map +1 -0
- package/dist/audit/ocsf.js +204 -0
- package/dist/audit/ocsf.js.map +1 -0
- package/dist/cli/hidden-prompt.d.ts.map +1 -1
- package/dist/cli/hidden-prompt.js +55 -10
- package/dist/cli/hidden-prompt.js.map +1 -1
- package/dist/cli/messages.d.ts +40 -8
- package/dist/cli/messages.d.ts.map +1 -1
- package/dist/cli/messages.js +34 -8
- package/dist/cli/messages.js.map +1 -1
- package/dist/client.d.ts +26 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +129 -0
- package/dist/client.js.map +1 -0
- package/dist/compatibility.d.ts +199 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +419 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/index.d.ts +19 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/policies/audit-trail.d.ts +25 -0
- package/dist/policies/audit-trail.d.ts.map +1 -0
- package/dist/policies/audit-trail.js +31 -0
- package/dist/policies/audit-trail.js.map +1 -0
- package/dist/sinks/index.d.ts +9 -0
- package/dist/sinks/index.d.ts.map +1 -0
- package/dist/sinks/index.js +5 -0
- package/dist/sinks/index.js.map +1 -0
- package/dist/sinks/jsonl.d.ts +16 -0
- package/dist/sinks/jsonl.d.ts.map +1 -0
- package/dist/sinks/jsonl.js +51 -0
- package/dist/sinks/jsonl.js.map +1 -0
- package/dist/sinks/otel.d.ts +22 -0
- package/dist/sinks/otel.d.ts.map +1 -0
- package/dist/sinks/otel.js +155 -0
- package/dist/sinks/otel.js.map +1 -0
- package/dist/sinks/queue.d.ts +12 -0
- package/dist/sinks/queue.d.ts.map +1 -0
- package/dist/sinks/queue.js +89 -0
- package/dist/sinks/queue.js.map +1 -0
- package/dist/sinks/syslog.d.ts +17 -0
- package/dist/sinks/syslog.d.ts.map +1 -0
- package/dist/sinks/syslog.js +103 -0
- package/dist/sinks/syslog.js.map +1 -0
- package/dist/sinks/types.d.ts +27 -0
- package/dist/sinks/types.d.ts.map +1 -0
- package/dist/sinks/types.js +18 -0
- package/dist/sinks/types.js.map +1 -0
- package/dist/vault/policy.d.ts +64 -34
- package/dist/vault/policy.d.ts.map +1 -1
- package/dist/vault/policy.js +109 -67
- package/dist/vault/policy.js.map +1 -1
- package/dist/vault/session-vault.d.ts +43 -0
- package/dist/vault/session-vault.d.ts.map +1 -1
- package/dist/vault/session-vault.js +323 -36
- package/dist/vault/session-vault.js.map +1 -1
- package/dist/vault/sidecar.d.ts +9 -0
- package/dist/vault/sidecar.d.ts.map +1 -1
- package/dist/vault/sidecar.js +72 -3
- package/dist/vault/sidecar.js.map +1 -1
- package/dist/vault/types.d.ts +16 -9
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/vault-env.d.ts +41 -62
- package/dist/vault/vault-env.d.ts.map +1 -1
- package/dist/vault/vault-env.js +139 -75
- package/dist/vault/vault-env.js.map +1 -1
- package/dist/vault/vault-gpg.d.ts +1 -0
- package/dist/vault/vault-gpg.d.ts.map +1 -1
- package/dist/vault/vault-gpg.js +1 -0
- package/dist/vault/vault-gpg.js.map +1 -1
- package/dist/vault/vault-libsecret.d.ts +1 -0
- package/dist/vault/vault-libsecret.d.ts.map +1 -1
- package/dist/vault/vault-libsecret.js +7 -6
- package/dist/vault/vault-libsecret.js.map +1 -1
- package/dist/vault/vault-onepassword.d.ts +1 -0
- package/dist/vault/vault-onepassword.d.ts.map +1 -1
- package/dist/vault/vault-onepassword.js +1 -0
- package/dist/vault/vault-onepassword.js.map +1 -1
- package/dist/vault/vault-utils.d.ts +7 -6
- package/dist/vault/vault-utils.d.ts.map +1 -1
- package/dist/vault/vault-utils.js +8 -7
- package/dist/vault/vault-utils.js.map +1 -1
- package/dist/vault/vault-windows.d.ts +2 -1
- package/dist/vault/vault-windows.d.ts.map +1 -1
- package/dist/vault/vault-windows.js +12 -8
- package/dist/vault/vault-windows.js.map +1 -1
- package/dist/vault/vault.d.ts +6 -7
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +37 -193
- package/dist/vault/vault.js.map +1 -1
- package/package.json +8 -2
package/dist/cli/messages.js
CHANGED
|
@@ -1,14 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Auth
|
|
2
|
+
* Auth CLI message catalog — the shared strings for the credential lifecycle a
|
|
3
|
+
* consuming CLI drives on top of this vault (`login`, `logout`, `auth status`,
|
|
4
|
+
* `auth refresh`, device flow, api-key entry).
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* Scope (#217 C6-34). The previous header claimed "all user-visible strings for
|
|
7
|
+
* the auth module", which was never true of this package — there is no auth
|
|
8
|
+
* module here, and only one entry had an in-package call site. The verified
|
|
9
|
+
* scope is:
|
|
10
|
+
*
|
|
11
|
+
* - IN — the auth/device-flow/token lifecycle listed above, driven by the
|
|
12
|
+
* consuming CLI, plus the one credential-storage warning this package
|
|
13
|
+
* itself emits: `warning.envVaultNoStorage`, from `EnvVault.store()` in
|
|
14
|
+
* `../vault/vault-env.ts`.
|
|
15
|
+
* - OUT — the `centient secrets …` operator CLI in `./secrets-cli.ts` and the
|
|
16
|
+
* `[secrets] …` vault diagnostics under `../vault/`. Those are
|
|
17
|
+
* command-specific and carry their own next-step lines; funnelling them
|
|
18
|
+
* through a flat catalog would drop that specificity, so they are
|
|
19
|
+
* deliberately not catalog entries.
|
|
20
|
+
*
|
|
21
|
+
* This catalog is part of the package's public surface — import it, do not copy
|
|
22
|
+
* it. It is exported precisely so a consuming CLI stops maintaining a fork:
|
|
23
|
+
* before #217, `centient` carried a byte-identical copy at
|
|
24
|
+
* `packages/centient/src/auth/messages.ts` that had already drifted on
|
|
25
|
+
* `warning.envVaultNoStorage` (the single entry this package consumes, and so
|
|
26
|
+
* the single entry that had been updated here).
|
|
27
|
+
*
|
|
28
|
+
* i18n-ready: no message value interpolates at the call site. Parameterized
|
|
29
|
+
* messages are template functions that take their parameters and return the
|
|
30
|
+
* finished string, so a translation layer can replace the catalog wholesale.
|
|
7
31
|
*
|
|
8
32
|
* Usage:
|
|
9
|
-
* import { AUTH_MESSAGES } from
|
|
10
|
-
* process.stderr.write(AUTH_MESSAGES.error.vaultWriteFailed +
|
|
11
|
-
* process.stderr.write(
|
|
33
|
+
* import { AUTH_MESSAGES } from "@centient/secrets";
|
|
34
|
+
* process.stderr.write(AUTH_MESSAGES.error.vaultWriteFailed + "\n");
|
|
35
|
+
* process.stderr.write(
|
|
36
|
+
* AUTH_MESSAGES.info.loginPrompt("https://auth.example.com") + "\n",
|
|
37
|
+
* );
|
|
12
38
|
*/
|
|
13
39
|
// =============================================================================
|
|
14
40
|
// Message catalog
|
|
@@ -45,7 +71,7 @@ export const AUTH_MESSAGES = {
|
|
|
45
71
|
revokeNetworkFailure: "Could not reach server to revoke token — local credentials have been removed.",
|
|
46
72
|
noCredentialsFound: "No stored credentials found. Run `centient login` to authenticate.",
|
|
47
73
|
sessionExpiredIdle: "Session expired due to inactivity.",
|
|
48
|
-
envVaultNoStorage: "No secure credential storage available. Install libsecret (Linux: apt install libsecret-tools) or GPG for persistent storage.
|
|
74
|
+
envVaultNoStorage: "No secure credential storage available. Install libsecret (Linux: apt install libsecret-tools) or GPG for persistent storage. The environment fallback is read-only; set ENGRAM_API_KEY for auth-token or the key's CENTIENT_SECRET_* variable.",
|
|
49
75
|
},
|
|
50
76
|
info: {
|
|
51
77
|
loginPrompt: (verificationUri) => `Visit the following URL to authorize this device:\n ${verificationUri}`,
|
package/dist/cli/messages.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/cli/messages.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/cli/messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,gFAAgF;AAChF,kBAAkB;AAClB,gFAAgF;AAEhF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE;QACP,QAAQ,EAAE,mDAAmD;QAC7D,SAAS,EAAE,+CAA+C;QAC1D,WAAW,EAAE,iCAAiC;QAC9C,cAAc,EAAE,+BAA+B;QAC/C,YAAY,EAAE,mCAAmC;QACjD,cAAc,EAAE,0BAA0B;KAC3C;IAED,KAAK,EAAE;QACL,gBAAgB,EAAE,uCAAuC;QACzD,eAAe,EAAE,wCAAwC;QACzD,iBAAiB,EAAE,0CAA0C;QAC7D,gBAAgB,EAAE,mCAAmC;QACrD,iBAAiB,EAAE,mDAAmD;QACtE,sBAAsB,EAAE,4CAA4C;QACpE,iBAAiB,EAAE,8CAA8C;QACjE,YAAY,EAAE,wDAAwD;QACtE,YAAY,EAAE,uBAAuB;QACrC,cAAc,EAAE,6CAA6C;QAC7D,YAAY,EAAE,sCAAsC;QACpD,aAAa,EAAE,0DAA0D;QACzE,YAAY,EAAE,sDAAsD;QACpE,mBAAmB,EAAE,CAAC,GAAW,EAAU,EAAE,CAC3C,4BAA4B,GAAG,qCAAqC;QACtE,uBAAuB,EACrB,sDAAsD;QACxD,iBAAiB,EAAE,CAAC,GAAW,EAAU,EAAE,CACzC,wBAAwB,GAAG,4CAA4C;KAC1E;IAED,OAAO,EAAE;QACP,iBAAiB,EAAE,CAAC,OAAe,EAAU,EAAE,CAC7C,yBAAyB,OAAO,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,sCAAsC;QAC1G,oBAAoB,EAClB,+EAA+E;QACjF,kBAAkB,EAChB,oEAAoE;QACtE,kBAAkB,EAAE,oCAAoC;QACxD,iBAAiB,EACf,iPAAiP;KACpP;IAED,IAAI,EAAE;QACJ,WAAW,EAAE,CAAC,eAAuB,EAAU,EAAE,CAC/C,wDAAwD,eAAe,EAAE;QAC3E,eAAe,EAAE,CAAC,QAAgB,EAAU,EAAE,CAC5C,qCAAqC,QAAQ,EAAE;QACjD,WAAW,EAAE,CAAC,OAAe,EAAU,EAAE,CACvC,iCAAiC,OAAO,cAAc;QACxD,iBAAiB,EACf,+EAA+E;QACjF,uBAAuB,EAAE,CAAC,SAAiB,EAAU,EAAE,CACrD,mCAAmC,SAAS,GAAG;QACjD,yBAAyB,EAAE,0CAA0C;QACrE,sBAAsB,EAAE,CAAC,OAAe,EAAU,EAAE,CAClD,8BAA8B,OAAO,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI;QAC7E,SAAS,EAAE,CAAC,SAAiB,EAAU,EAAE,CAAC,UAAU,SAAS,EAAE;QAC/D,cAAc,EAAE,gBAAgB;QAChC,aAAa,EAAE,uCAAuC;KACvD;CACO,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type PolicyRunner, type SecretsOperationContext, type SecretsPolicy } from "./vault/policy.js";
|
|
2
|
+
import type { SecretsProvider } from "./vault/types.js";
|
|
3
|
+
export interface CreateSecretsClientOptions {
|
|
4
|
+
/** Credential-value storage provider used by this client only. */
|
|
5
|
+
readonly provider: SecretsProvider;
|
|
6
|
+
/** Policy membership is snapshotted at construction for this client. */
|
|
7
|
+
readonly policies?: readonly SecretsPolicy[];
|
|
8
|
+
/** Honest event identity when a legacy provider has no `name`. */
|
|
9
|
+
readonly providerName?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SecretsClient {
|
|
12
|
+
readonly providerName: string;
|
|
13
|
+
storeCredential(key: string, value: string, context?: SecretsOperationContext): Promise<boolean>;
|
|
14
|
+
getCredential(key: string, context?: SecretsOperationContext): Promise<string | null>;
|
|
15
|
+
deleteCredential(key: string, context?: SecretsOperationContext): Promise<boolean>;
|
|
16
|
+
listCredentials(prefix?: string, context?: SecretsOperationContext): Promise<string[]>;
|
|
17
|
+
isSessionValid(): boolean;
|
|
18
|
+
}
|
|
19
|
+
type InternalSecretsClientOptions = Omit<CreateSecretsClientOptions, "policies"> & {
|
|
20
|
+
readonly policyRunner: PolicyRunner;
|
|
21
|
+
};
|
|
22
|
+
export declare function createSecretsClient(options: CreateSecretsClientOptions): SecretsClient;
|
|
23
|
+
/** @internal Legacy default-client construction seam. */
|
|
24
|
+
export declare function createSecretsClientWithPolicyRunner(options: InternalSecretsClientOptions): SecretsClient;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EAKjB,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAOxD,MAAM,WAAW,0BAA0B;IACzC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,kEAAkE;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,eAAe,CACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,aAAa,CACX,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1B,gBAAgB,CACd,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,eAAe,CACb,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACrB,cAAc,IAAI,OAAO,CAAC;CAC3B;AAED,KAAK,4BAA4B,GAAG,IAAI,CACtC,0BAA0B,EAC1B,UAAU,CACX,GAAG;IACF,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;CACrC,CAAC;AAoNF,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,aAAa,CAMf;AAED,yDAAyD;AACzD,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,4BAA4B,GACpC,aAAa,CAMf"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { createPolicyRunner, rejectedEventType, } from "./vault/policy.js";
|
|
2
|
+
import { isValidKey, isValidKeyPrefix } from "./vault/vault-utils.js";
|
|
3
|
+
import { InvalidCredentialKeyError } from "./vault/session-vault-errors.js";
|
|
4
|
+
const SESSION_TTL_MS = 4 * 60 * 60 * 1000;
|
|
5
|
+
const PROVIDER_FAILURE_ERROR = "provider operation failed";
|
|
6
|
+
function operationStart() {
|
|
7
|
+
return {
|
|
8
|
+
timestamp: new Date().toISOString(),
|
|
9
|
+
monotonicMs: performance.now(),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function operationWithContext(fields, context) {
|
|
13
|
+
const caller = context?.caller;
|
|
14
|
+
return Object.freeze({
|
|
15
|
+
...fields,
|
|
16
|
+
...(caller
|
|
17
|
+
? {
|
|
18
|
+
caller: Object.freeze({
|
|
19
|
+
id: caller.id,
|
|
20
|
+
...(caller.kind !== undefined ? { kind: caller.kind } : {}),
|
|
21
|
+
}),
|
|
22
|
+
}
|
|
23
|
+
: {}),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
class SecretsClientImpl {
|
|
27
|
+
provider;
|
|
28
|
+
policies;
|
|
29
|
+
providerName;
|
|
30
|
+
lastAccessAt = null;
|
|
31
|
+
constructor(provider, policies, providerName) {
|
|
32
|
+
this.provider = provider;
|
|
33
|
+
this.policies = policies;
|
|
34
|
+
const candidate = providerName ?? provider.name;
|
|
35
|
+
this.providerName = candidate?.trim() || "unknown";
|
|
36
|
+
}
|
|
37
|
+
isSessionValid() {
|
|
38
|
+
return (this.lastAccessAt !== null &&
|
|
39
|
+
Date.now() - this.lastAccessAt < SESSION_TTL_MS);
|
|
40
|
+
}
|
|
41
|
+
async storeCredential(key, value, context) {
|
|
42
|
+
const operation = operationWithContext({ type: "write", key }, context);
|
|
43
|
+
this.assertValidOperation(operation);
|
|
44
|
+
return this.execute(operation, "credential_write_failed", () => this.provider.store(key, value), (success) => success ? "credential_written" : "credential_write_failed", (success) => {
|
|
45
|
+
if (success)
|
|
46
|
+
this.lastAccessAt = Date.now();
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async getCredential(key, context) {
|
|
50
|
+
const operation = operationWithContext({ type: "read", key }, context);
|
|
51
|
+
this.assertValidOperation(operation);
|
|
52
|
+
return this.execute(operation, "credential_read_failed", () => this.provider.retrieve(key), (value) => value === null ? "credential_read_missing" : "credential_read", (value) => {
|
|
53
|
+
if (value !== null)
|
|
54
|
+
this.lastAccessAt = Date.now();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async deleteCredential(key, context) {
|
|
58
|
+
const operation = operationWithContext({ type: "delete", key }, context);
|
|
59
|
+
this.assertValidOperation(operation);
|
|
60
|
+
return this.execute(operation, "credential_delete_failed", () => this.provider.delete(key), (success) => success ? "credential_deleted" : "credential_delete_failed");
|
|
61
|
+
}
|
|
62
|
+
async listCredentials(prefix, context) {
|
|
63
|
+
const operation = operationWithContext({ type: "enumerate", ...(prefix !== undefined ? { prefix } : {}) }, context);
|
|
64
|
+
this.assertValidOperation(operation);
|
|
65
|
+
return this.execute(operation, "credential_enumerate_failed", () => this.provider.listKeys(prefix), () => "credential_enumerated", (keys) => {
|
|
66
|
+
if (keys.length > 0)
|
|
67
|
+
this.lastAccessAt = Date.now();
|
|
68
|
+
}, (keys) => ({ keyCount: keys.length }));
|
|
69
|
+
}
|
|
70
|
+
assertValidOperation(operation) {
|
|
71
|
+
let error;
|
|
72
|
+
if (operation.type === "enumerate") {
|
|
73
|
+
if (operation.prefix !== undefined &&
|
|
74
|
+
!isValidKeyPrefix(operation.prefix)) {
|
|
75
|
+
error = new InvalidCredentialKeyError(operation.prefix, "enumerate", "prefix");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (operation.key !== undefined && !isValidKey(operation.key)) {
|
|
79
|
+
error = new InvalidCredentialKeyError(operation.key, operation.type, "key");
|
|
80
|
+
}
|
|
81
|
+
if (!error)
|
|
82
|
+
return;
|
|
83
|
+
const start = operationStart();
|
|
84
|
+
this.policies.runAfter(this.makeEvent(operation, rejectedEventType(operation), start, { error: error.message }));
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
async execute(operation, failedType, invoke, successType, onSuccess, extras) {
|
|
88
|
+
const start = operationStart();
|
|
89
|
+
let frame;
|
|
90
|
+
frame = await this.policies.runBefore(operation, (error) => this.makeEvent(operation, rejectedEventType(operation), start, { error }));
|
|
91
|
+
let value;
|
|
92
|
+
try {
|
|
93
|
+
value = await invoke();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
this.policies.runAfter(this.makeEvent(operation, failedType, start, {
|
|
97
|
+
// Providers receive credential values on writes and may include one
|
|
98
|
+
// in a thrown message. Preserve the original error for the caller,
|
|
99
|
+
// but never forward provider-controlled text into an audit event.
|
|
100
|
+
error: PROVIDER_FAILURE_ERROR,
|
|
101
|
+
}), frame);
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
onSuccess?.(value);
|
|
105
|
+
this.policies.runAfter(this.makeEvent(operation, successType(value), start, extras?.(value)), frame);
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
makeEvent(operation, type, start, extras = {}) {
|
|
109
|
+
return {
|
|
110
|
+
type,
|
|
111
|
+
// OCSF `time` is the operation start, not completion time.
|
|
112
|
+
timestamp: start.timestamp,
|
|
113
|
+
backend: this.providerName,
|
|
114
|
+
operation,
|
|
115
|
+
...(operation.key !== undefined ? { key: operation.key } : {}),
|
|
116
|
+
...(operation.prefix !== undefined ? { prefix: operation.prefix } : {}),
|
|
117
|
+
...extras,
|
|
118
|
+
durationMs: performance.now() - start.monotonicMs,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function createSecretsClient(options) {
|
|
123
|
+
return new SecretsClientImpl(options.provider, createPolicyRunner(options.policies ?? []), options.providerName);
|
|
124
|
+
}
|
|
125
|
+
/** @internal Legacy default-client construction seam. */
|
|
126
|
+
export function createSecretsClientWithPolicyRunner(options) {
|
|
127
|
+
return new SecretsClientImpl(options.provider, options.policyRunner, options.providerName);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The compatibility floor: what an OLD `@centient/secrets` silently does wrong,
|
|
3
|
+
* published as data so a consumer can grade itself (#214).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* Five consumers pin this package at four disjoint minors (`^0.5.0` … `0.10.0`)
|
|
8
|
+
* with no negotiation surface between them and the provider. Several releases
|
|
9
|
+
* closed defects whose only symptom, at the old version, is **silence**: a
|
|
10
|
+
* denied credential operation that leaves no audit trace, a keychain write that
|
|
11
|
+
* reports success into a keychain this context's reader cannot see, a malformed
|
|
12
|
+
* key that stores on one backend and reads as absent on the next. A consumer
|
|
13
|
+
* running such a version has no way to learn that from the package — the
|
|
14
|
+
* behaviour looks fine and the logs look clean.
|
|
15
|
+
*
|
|
16
|
+
* So the provider publishes the list. {@link COMPATIBILITY_FLOOR} names each
|
|
17
|
+
* closed gap, the version that closed it, and the symptom it presented before
|
|
18
|
+
* then; {@link assessCompatibility} turns an installed version into a grade a
|
|
19
|
+
* `doctor` command can print.
|
|
20
|
+
*
|
|
21
|
+
* ## What this is NOT
|
|
22
|
+
*
|
|
23
|
+
* **Never a boot-time refusal.** Nothing here runs at import, nothing throws
|
|
24
|
+
* from a constructor, and no vault path consults it. A package that refuses to
|
|
25
|
+
* load because the caller is old converts a documentation problem into an
|
|
26
|
+
* outage. Every function in this module is pure, total, and advisory: malformed
|
|
27
|
+
* input comes back as a typed `"unknown"` grade carrying the reason (P2, No
|
|
28
|
+
* Silent Degradation; P10, Honest Uncertainty), never as a throw.
|
|
29
|
+
*
|
|
30
|
+
* ## What a consumer does with it
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { assessCompatibility, SECRETS_PACKAGE_VERSION } from "@centient/secrets";
|
|
34
|
+
*
|
|
35
|
+
* const assessment = assessCompatibility(SECRETS_PACKAGE_VERSION);
|
|
36
|
+
* if (assessment.grade !== "ok") {
|
|
37
|
+
* for (const gap of assessment.openGaps) {
|
|
38
|
+
* report(`${gap.severity}: ${gap.symptom} (fixed in ${gap.closedIn}, ${gap.reference})`);
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* `SECRETS_PACKAGE_VERSION` is the version of the build the consumer actually
|
|
44
|
+
* imported, so the assessment describes the code in that tree — not whatever is
|
|
45
|
+
* latest on the registry. A consumer auditing a *manifest* range instead (`the
|
|
46
|
+
* pin says ^0.6.0 — what does that admit at worst?`) uses {@link assessPin}.
|
|
47
|
+
*
|
|
48
|
+
* Issue: centient-labs/centient-sdk#214 (findings C6-27, C6-29, C6-61).
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* The version of THIS build of `@centient/secrets`.
|
|
52
|
+
*
|
|
53
|
+
* Kept in step with `package.json` two ways: `scripts/sync-claudemd-versions.mjs`
|
|
54
|
+
* rewrites it during `pnpm run version-packages` (the same step that syncs the
|
|
55
|
+
* CLAUDE.md package table), and `tests/compatibility.test.ts` fails the build if
|
|
56
|
+
* the two ever disagree. A stale constant here would misgrade every consumer, so
|
|
57
|
+
* drift is a test failure rather than a silent wrong answer.
|
|
58
|
+
*/
|
|
59
|
+
export declare const SECRETS_PACKAGE_VERSION = "0.11.0";
|
|
60
|
+
/**
|
|
61
|
+
* The oldest version {@link COMPATIBILITY_FLOOR} can honestly describe.
|
|
62
|
+
*
|
|
63
|
+
* `0.5.0` is the oldest release any current consumer pins, and the oldest one
|
|
64
|
+
* whose behaviour the table's entries were written against. Below it the table
|
|
65
|
+
* is not wrong so much as **incomplete** — returning its short list for a 0.4.x
|
|
66
|
+
* install would understate what is open — so {@link assessCompatibility} grades
|
|
67
|
+
* such a version `"unsupported"` and says so, rather than quietly reporting the
|
|
68
|
+
* gaps it happens to know about.
|
|
69
|
+
*
|
|
70
|
+
* This is an epistemic limit on the table, not a support policy and not a gate:
|
|
71
|
+
* an `"unsupported"` grade still returns every gap the table does know about.
|
|
72
|
+
*/
|
|
73
|
+
export declare const MIN_ASSESSABLE_VERSION = "0.5.0";
|
|
74
|
+
/** How badly the gap bites a consumer still running below `closedIn`. */
|
|
75
|
+
export type GapSeverity = "high" | "medium" | "low";
|
|
76
|
+
/**
|
|
77
|
+
* One known behavioural gap, keyed by the version that closed it.
|
|
78
|
+
*
|
|
79
|
+
* A gap is **open** for an installed version `v` exactly when
|
|
80
|
+
* `v < closedIn` — there is no upper bound, because a fix that shipped is not
|
|
81
|
+
* un-shipped. Everything here is value-free public metadata: no credential
|
|
82
|
+
* material, no host paths, nothing that changes at runtime.
|
|
83
|
+
*/
|
|
84
|
+
export interface CompatibilityGap {
|
|
85
|
+
/** Stable machine-readable id. Never renamed — consumers may suppress by id. */
|
|
86
|
+
readonly id: string;
|
|
87
|
+
/** The first release in which the gap is closed. A valid `major.minor.patch`. */
|
|
88
|
+
readonly closedIn: string;
|
|
89
|
+
/** How badly this bites a consumer still below `closedIn`. */
|
|
90
|
+
readonly severity: GapSeverity;
|
|
91
|
+
/** One line, consumer-facing: what the OLD version does wrong. */
|
|
92
|
+
readonly symptom: string;
|
|
93
|
+
/** Issue or PR that closed it, `owner/repo#n`. */
|
|
94
|
+
readonly reference: string;
|
|
95
|
+
/**
|
|
96
|
+
* What the consumer must change when it adopts the fix, when adopting is not
|
|
97
|
+
* a pure no-op. Absent means "bump and nothing else". This is the field that
|
|
98
|
+
* turns the table from a scorecard into a bump plan.
|
|
99
|
+
*/
|
|
100
|
+
readonly adoptionNote?: string;
|
|
101
|
+
/** The C6 audit finding this gap corresponds to, where one exists. */
|
|
102
|
+
readonly finding?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The published floor — deeply frozen at module initialization (every field on
|
|
106
|
+
* a {@link CompatibilityGap} is a primitive, so freezing each entry plus the
|
|
107
|
+
* array is a complete freeze). `assessCompatibility()` defaults to this same
|
|
108
|
+
* object, so a runtime mutation — a JS consumer, a test helper, a cast past
|
|
109
|
+
* the `readonly` type — would silently change every later assessment in the
|
|
110
|
+
* process. Frozen, the mutation throws at the mutation site instead
|
|
111
|
+
* (mb:f/7e54ba; the same no-silent-degradation stance as the rest of this
|
|
112
|
+
* module).
|
|
113
|
+
*/
|
|
114
|
+
export declare const COMPATIBILITY_FLOOR: readonly CompatibilityGap[];
|
|
115
|
+
/** The grade a consumer's installed version earns against the floor. */
|
|
116
|
+
export type CompatibilityGrade =
|
|
117
|
+
/** At or above every known fix. Nothing in the table is open. */
|
|
118
|
+
"ok"
|
|
119
|
+
/** Assessable, but one or more known gaps are open. `openGaps` lists them. */
|
|
120
|
+
| "degraded"
|
|
121
|
+
/** Below {@link MIN_ASSESSABLE_VERSION}: the table cannot claim to be complete. */
|
|
122
|
+
| "unsupported"
|
|
123
|
+
/** The version could not be parsed. `reason` says why. Never a throw. */
|
|
124
|
+
| "unknown";
|
|
125
|
+
/**
|
|
126
|
+
* The result of grading one version against the floor. Every field is derived
|
|
127
|
+
* and value-free; the input is echoed back so a caller can see what was graded
|
|
128
|
+
* (P6, Single Source of Truth — echo interpreted parameters).
|
|
129
|
+
*/
|
|
130
|
+
export interface CompatibilityAssessment {
|
|
131
|
+
readonly grade: CompatibilityGrade;
|
|
132
|
+
/** The version as given, echoed verbatim — including unparseable input. */
|
|
133
|
+
readonly installedVersion: string;
|
|
134
|
+
/** The version of the build that produced this assessment. */
|
|
135
|
+
readonly currentVersion: string;
|
|
136
|
+
/** The floor below which the table is incomplete. */
|
|
137
|
+
readonly minAssessableVersion: string;
|
|
138
|
+
/**
|
|
139
|
+
* Gaps open at `installedVersion`, oldest fix first. Empty for `"ok"` and for
|
|
140
|
+
* `"unknown"` — and for `"unknown"` that emptiness means `not assessed`, which
|
|
141
|
+
* is why the grade, not the list length, is what a caller branches on.
|
|
142
|
+
*/
|
|
143
|
+
readonly openGaps: readonly CompatibilityGap[];
|
|
144
|
+
/** The worst severity among `openGaps`, or `null` when there are none. */
|
|
145
|
+
readonly highestSeverity: GapSeverity | null;
|
|
146
|
+
/** One line suitable for a doctor's status column. */
|
|
147
|
+
readonly summary: string;
|
|
148
|
+
/** Why the grade is `"unknown"` or `"unsupported"`. Absent otherwise. */
|
|
149
|
+
readonly reason?: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Grade an installed version against the compatibility floor.
|
|
153
|
+
*
|
|
154
|
+
* Pure and total: it reads no environment, touches no keychain, and **never
|
|
155
|
+
* throws** — a version string it cannot parse comes back as
|
|
156
|
+
* `grade: "unknown"` naming the problem. Totality is enforced here rather than
|
|
157
|
+
* assumed of the parser: input is narrowed by this module's own guard, so a JS
|
|
158
|
+
* caller handing it `null`, `undefined`, a number or an object gets the same
|
|
159
|
+
* typed `"unknown"` result as a misspelt version, never an exception. Call it
|
|
160
|
+
* from a `doctor`, a startup log line, or a CI check; do not call it from a
|
|
161
|
+
* code path that would refuse to run on the answer.
|
|
162
|
+
*
|
|
163
|
+
* @param installedVersion - the version actually installed in the consumer's
|
|
164
|
+
* tree. Import {@link SECRETS_PACKAGE_VERSION} for that; a leading `v` and
|
|
165
|
+
* surrounding whitespace are tolerated.
|
|
166
|
+
* @param floor - the gap table to grade against. Defaults to
|
|
167
|
+
* {@link COMPATIBILITY_FLOOR}; injectable so a test can grade a fixture table
|
|
168
|
+
* without pinning itself to the shipped one.
|
|
169
|
+
*/
|
|
170
|
+
export declare function assessCompatibility(installedVersion: string, floor?: readonly CompatibilityGap[]): CompatibilityAssessment;
|
|
171
|
+
/**
|
|
172
|
+
* The lowest version a dependency range admits, or `null` when the range form
|
|
173
|
+
* is one this helper does not understand.
|
|
174
|
+
*
|
|
175
|
+
* Deliberately narrow: it recognises the forms that actually appear in the
|
|
176
|
+
* consumers' manifests — `^x.y.z`, `~x.y.z`, `>=x.y.z` and a bare `x.y.z` — and
|
|
177
|
+
* returns `null` for everything else rather than guessing. A guess here would
|
|
178
|
+
* grade the wrong version and report a clean bill of health for a pin nobody
|
|
179
|
+
* checked.
|
|
180
|
+
*
|
|
181
|
+
* The accepted grammar is matched whole and enumerated on
|
|
182
|
+
* {@link SUPPORTED_RANGE}; nothing outside it is partially interpreted. Total:
|
|
183
|
+
* a non-string, an empty string, and every unsupported form all return `null`.
|
|
184
|
+
*/
|
|
185
|
+
export declare function lowestVersionInRange(range: string): string | null;
|
|
186
|
+
/**
|
|
187
|
+
* Grade a manifest **pin** by its worst admissible version.
|
|
188
|
+
*
|
|
189
|
+
* `assessCompatibility` answers "what is open in the build I imported"; this
|
|
190
|
+
* answers "what could be open in any build this pin admits". A `^0.6.0` pin can
|
|
191
|
+
* resolve to any 0.6.x, so the version worth grading is its base — which is also
|
|
192
|
+
* the one a lockfile that has never been refreshed is most likely holding.
|
|
193
|
+
*
|
|
194
|
+
* Returns `grade: "unknown"` carrying the reason for a range form
|
|
195
|
+
* {@link lowestVersionInRange} does not recognise — including a non-string a JS
|
|
196
|
+
* caller slipped past the signature. Never throws.
|
|
197
|
+
*/
|
|
198
|
+
export declare function assessPin(pin: string, floor?: readonly CompatibilityGap[]): CompatibilityAssessment;
|
|
199
|
+
//# sourceMappingURL=compatibility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compatibility.d.ts","sourceRoot":"","sources":["../src/compatibility.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAIH;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,UAAU,CAAC;AAE9C,yEAAyE;AACzE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAQpD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AA+ED;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,gBAAgB,EAE1D,CAAC;AA4DF,wEAAwE;AACxE,MAAM,MAAM,kBAAkB;AAC5B,iEAAiE;AAC/D,IAAI;AACN,8EAA8E;GAC5E,UAAU;AACZ,mFAAmF;GACjF,aAAa;AACf,yEAAyE;GACvE,SAAS,CAAC;AAEd;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,2EAA2E;IAC3E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,8DAA8D;IAC9D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,qDAAqD;IACrD,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC/C,0EAA0E;IAC1E,QAAQ,CAAC,eAAe,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7C,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,MAAM,EACxB,KAAK,GAAE,SAAS,gBAAgB,EAAwB,GACvD,uBAAuB,CAwEzB;AA0FD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,SAAS,gBAAgB,EAAwB,GACvD,uBAAuB,CAezB"}
|