@coffre/core 0.7.0 → 0.8.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.
@@ -605,8 +605,10 @@ export declare function unseal<T>(key: Uint8Array, sealed: string | undefined |
605
605
  //#region src/identity/tokens.d.ts
606
606
  /**
607
607
  * Bearer credentials coffre issues itself: browser sessions, CLI sessions,
608
- * service tokens, and personal tokens, which act as the person who made
609
- * them within the scope they named.
608
+ * service tokens, personal tokens, which act as the person who made
609
+ * them within the scope they named, and handles, which reach nothing but
610
+ * the credential proxy (`@coffre/server/plugins/credential-proxy`): the
611
+ * stand-in a person's app holds in place of a secret's value.
610
612
  *
611
613
  * A token is a kind prefix and 32 random bytes, e.g.
612
614
  * `coffre_cli_Qm9Y...`. The prefix tells a person (or a secret scanner) what a
@@ -615,7 +617,7 @@ export declare function unseal<T>(key: Uint8Array, sealed: string | undefined |
615
617
  * right tool here, unlike for passwords: 256 bits of randomness leave nothing
616
618
  * to brute-force.
617
619
  */
618
- export type CredentialKind = 'browser' | 'cli' | 'service' | 'personal';
620
+ export type CredentialKind = 'browser' | 'cli' | 'service' | 'personal' | 'handle';
619
621
  export declare function generateToken(kind: CredentialKind): string;
620
622
  /** Whether a string has the shape of a coffre token, before any lookup. */
621
623
  export declare function isCoffreToken(value: string): boolean;
package/dist/identity.js CHANGED
@@ -997,9 +997,10 @@ const PREFIX = {
997
997
  browser: "coffre_web_",
998
998
  cli: "coffre_cli_",
999
999
  service: "coffre_svc_",
1000
- personal: "coffre_pat_"
1000
+ personal: "coffre_pat_",
1001
+ handle: "coffre_use_"
1001
1002
  };
1002
- const TOKEN = /^coffre_(web|cli|svc|pat)_[A-Za-z0-9_-]{43}$/;
1003
+ const TOKEN = /^coffre_(web|cli|svc|pat|use)_[A-Za-z0-9_-]{43}$/;
1003
1004
  function generateToken(kind) {
1004
1005
  return PREFIX[kind] + randomBytes(32).toString("base64url");
1005
1006
  }
package/dist/schemas.d.ts CHANGED
@@ -39,11 +39,11 @@ export declare const principalType: z.ZodEnum<{
39
39
  }>;
40
40
  export declare const principalId: z.ZodString;
41
41
  export declare const instanceRole: z.ZodEnum<{
42
- member: "member";
43
- auditor: "auditor";
44
42
  developer: "developer";
45
- admin: "admin";
43
+ auditor: "auditor";
46
44
  owner: "owner";
45
+ member: "member";
46
+ admin: "admin";
47
47
  }>;
48
48
  /** Which projects or environments a scope takes in, by slug: `all`, `{ only: [...] }` or `{ except: [...] }`. */
49
49
  export declare const scopeFilter: z.ZodUnion<readonly [z.ZodLiteral<"all">, z.ZodObject<{
package/dist/vault.d.ts CHANGED
@@ -254,6 +254,12 @@ export type RefusalCode =
254
254
  'bulk_limit' |
255
255
  /** The wrapped key does not belong to the secret it was presented as, or a reference is not the vault's. */
256
256
  'bad_claim' |
257
+ /**
258
+ * A person asked for values to be handed back, where people get stand-ins
259
+ * (`people: 'stand-ins'`): their apps use values through the credential
260
+ * proxy instead, and only service accounts read them.
261
+ */
262
+ 'stand_ins' |
257
263
  /**
258
264
  * The project or environment was deleted for good: nothing under it is
259
265
  * opened or wrapped again, whatever grant would cover it.
@@ -332,8 +338,20 @@ export type KeyChecks = {
332
338
  seq: number;
333
339
  })[];
334
340
  };
335
- /** Why someone reads: shown in the log, and the same rules apply to each. A fork reads to `copy`. */
336
- export type Purpose = 'reveal' | 'run' | 'compare' | 'copy';
341
+ /**
342
+ * Why someone reads: shown in the log, and the same rules apply to each. A
343
+ * fork reads to `copy`. The credential proxy reads to `use`, a value it
344
+ * injects into a request and never hands back, or to `expose`, one the
345
+ * deployment lets people's apps hold. Where people get stand-ins
346
+ * (`people: 'stand-ins'`), a person opens nothing to `reveal`, `run` or
347
+ * `compare` (`HANDED_BACK`).
348
+ */
349
+ export type Purpose = 'reveal' | 'run' | 'compare' | 'copy' | 'use' | 'expose';
350
+ /**
351
+ * What a person never opens where people get stand-ins: values handed back
352
+ * to them, and a dry run's `compare`, which tells them whether a guess was right.
353
+ */
354
+ export declare const HANDED_BACK: readonly Purpose[];
337
355
  /** Ties the vault's entries to the app's request and audit rows. */
338
356
  type Correlation = {
339
357
  requestId?: string | null;
package/dist/vault.js CHANGED
@@ -54,5 +54,14 @@ const ACCESS_ACTIONS = [
54
54
  "access.grant",
55
55
  "access.revoke"
56
56
  ];
57
+ /**
58
+ * What a person never opens where people get stand-ins: values handed back
59
+ * to them, and a dry run's `compare`, which tells them whether a guess was right.
60
+ */
61
+ const HANDED_BACK = [
62
+ "reveal",
63
+ "run",
64
+ "compare"
65
+ ];
57
66
  //#endregion
58
- export { ACCESS_ACTIONS, checkpointMessage, checkpointVerifier, describeAccessFault, verifyCheckpoint };
67
+ export { ACCESS_ACTIONS, HANDED_BACK, checkpointMessage, checkpointVerifier, describeAccessFault, verifyCheckpoint };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffre/core",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "What coffre's packages share: roles, envelopes, identity, the audit chain and the vault's contract.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -89,7 +89,7 @@
89
89
  "@types/node": "26.1.1",
90
90
  "tsdown": "0.23.0",
91
91
  "typescript": "5.9.3",
92
- "@coffre/conformance": "0.7.0"
92
+ "@coffre/conformance": "0.8.0"
93
93
  },
94
94
  "scripts": {
95
95
  "build": "tsdown",
@@ -2,8 +2,10 @@ import { createHash, randomBytes } from 'node:crypto';
2
2
 
3
3
  /**
4
4
  * Bearer credentials coffre issues itself: browser sessions, CLI sessions,
5
- * service tokens, and personal tokens, which act as the person who made
6
- * them within the scope they named.
5
+ * service tokens, personal tokens, which act as the person who made
6
+ * them within the scope they named, and handles, which reach nothing but
7
+ * the credential proxy (`@coffre/server/plugins/credential-proxy`): the
8
+ * stand-in a person's app holds in place of a secret's value.
7
9
  *
8
10
  * A token is a kind prefix and 32 random bytes, e.g.
9
11
  * `coffre_cli_Qm9Y...`. The prefix tells a person (or a secret scanner) what a
@@ -12,16 +14,17 @@ import { createHash, randomBytes } from 'node:crypto';
12
14
  * right tool here, unlike for passwords: 256 bits of randomness leave nothing
13
15
  * to brute-force.
14
16
  */
15
- export type CredentialKind = 'browser' | 'cli' | 'service' | 'personal';
17
+ export type CredentialKind = 'browser' | 'cli' | 'service' | 'personal' | 'handle';
16
18
 
17
19
  const PREFIX: Record<CredentialKind, string> = {
18
20
  browser: 'coffre_web_',
19
21
  cli: 'coffre_cli_',
20
22
  service: 'coffre_svc_',
21
23
  personal: 'coffre_pat_',
24
+ handle: 'coffre_use_',
22
25
  };
23
26
 
24
- const TOKEN = /^coffre_(web|cli|svc|pat)_[A-Za-z0-9_-]{43}$/;
27
+ const TOKEN = /^coffre_(web|cli|svc|pat|use)_[A-Za-z0-9_-]{43}$/;
25
28
 
26
29
  export function generateToken(kind: CredentialKind): string {
27
30
  return PREFIX[kind] + randomBytes(32).toString('base64url');
package/src/vault.ts CHANGED
@@ -163,6 +163,12 @@ export type RefusalCode =
163
163
  | 'bulk_limit'
164
164
  /** The wrapped key does not belong to the secret it was presented as, or a reference is not the vault's. */
165
165
  | 'bad_claim'
166
+ /**
167
+ * A person asked for values to be handed back, where people get stand-ins
168
+ * (`people: 'stand-ins'`): their apps use values through the credential
169
+ * proxy instead, and only service accounts read them.
170
+ */
171
+ | 'stand_ins'
166
172
  /**
167
173
  * The project or environment was deleted for good: nothing under it is
168
174
  * opened or wrapped again, whatever grant would cover it.
@@ -228,8 +234,21 @@ export type WrappedKey = { kekProvider: string; kekId: string; kekVersion: strin
228
234
  */
229
235
  export type KeyChecks = { current: { kekProvider: string; kekId: string }; checks: (WrappedKey & { seq: number })[] };
230
236
 
231
- /** Why someone reads: shown in the log, and the same rules apply to each. A fork reads to `copy`. */
232
- export type Purpose = 'reveal' | 'run' | 'compare' | 'copy';
237
+ /**
238
+ * Why someone reads: shown in the log, and the same rules apply to each. A
239
+ * fork reads to `copy`. The credential proxy reads to `use`, a value it
240
+ * injects into a request and never hands back, or to `expose`, one the
241
+ * deployment lets people's apps hold. Where people get stand-ins
242
+ * (`people: 'stand-ins'`), a person opens nothing to `reveal`, `run` or
243
+ * `compare` (`HANDED_BACK`).
244
+ */
245
+ export type Purpose = 'reveal' | 'run' | 'compare' | 'copy' | 'use' | 'expose';
246
+
247
+ /**
248
+ * What a person never opens where people get stand-ins: values handed back
249
+ * to them, and a dry run's `compare`, which tells them whether a guess was right.
250
+ */
251
+ export const HANDED_BACK: readonly Purpose[] = ['reveal', 'run', 'compare'];
233
252
 
234
253
  /** Ties the vault's entries to the app's request and audit rows. */
235
254
  type Correlation = {