cursedbelt-core 2.6.0 → 2.7.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.
@@ -1,15 +1,17 @@
1
1
  /**
2
2
  * The one place a satellite's owner-password floor is decided.
3
3
  *
4
- * ── Why this is shared, and why the default is 9 ────────────────────────────
4
+ * ── Why this is shared, and why the default is 6 ────────────────────────────
5
5
  * Three apps had independently written a `MIN_PASSWORD_BYTES` constant into
6
6
  * their own `scripts/owner.ts`, and they had already drifted (9, 14, 14) with
7
7
  * a paragraph in each explaining itself against the others. A floor is a
8
8
  * POLICY, and a policy copied three times is three policies.
9
9
  *
10
- * The default is {@link DEFAULT_MIN_PASSWORD_BYTES} = 9, which is the floor the
11
- * owner wants for an ordinary satellite: long enough that it is not a PIN, short
12
- * enough that it does not push the owner toward writing it down or reusing one.
10
+ * The default is {@link DEFAULT_MIN_PASSWORD_BYTES} = 6 — the owner, 2026-09-24:
11
+ * *"make the minimum password length 6 characters"* (it was 9). It is a SIGN-IN
12
+ * floor: every door that uses it rate-limits guesses, so a short password costs
13
+ * an attacker attempts, not seconds. A secret that can be guessed OFFLINE (vault's
14
+ * passphrase, which derives its encryption key) raises it at its own call site.
13
15
  * Argon2id — what every caller hashes with — is what actually carries the cost
14
16
  * of a guess here; these apps have exactly ONE principal and no enumerable user
15
17
  * list, so the marginal value of characters 10–14 is small and the friction is
@@ -25,7 +27,7 @@
25
27
  * {@link resolveMinPasswordBytes} takes an optional override and **refuses to
26
28
  * go below the default**. An app that genuinely runs at higher stakes says so
27
29
  * at its own call site, in one visible argument, with a comment saying why.
28
- * No app overrides it today — the retired orch companion app did (14, as the single
30
+ * `vault` does (9, since 2026-09-24 — its passphrase is an encryption key). The retired orch companion app did (14, as the single
29
31
  * internet-facing door into the host that runs `claude` in every repo) until
30
32
  * the owner dropped it to the shared floor on 2026-07-26.
31
33
  *
@@ -38,12 +40,12 @@
38
40
  * they read, so a multi-byte character counts as more than one, which is the
39
41
  * conservative direction).
40
42
  */
41
- export declare const DEFAULT_MIN_PASSWORD_BYTES = 9;
43
+ export declare const DEFAULT_MIN_PASSWORD_BYTES = 6;
42
44
  /**
43
45
  * The floor this app enforces: the default, or a higher one it asks for.
44
46
  *
45
47
  * Throws on an override below the default rather than silently clamping. A
46
- * caller passing 6 believes it is enforcing 6; being handed 9 without a word is
48
+ * caller passing 4 believes it is enforcing 4; being handed 6 without a word is
47
49
  * how a security floor becomes folklore.
48
50
  */
49
51
  export declare function resolveMinPasswordBytes(override?: number): number;
@@ -1,15 +1,17 @@
1
1
  /**
2
2
  * The one place a satellite's owner-password floor is decided.
3
3
  *
4
- * ── Why this is shared, and why the default is 9 ────────────────────────────
4
+ * ── Why this is shared, and why the default is 6 ────────────────────────────
5
5
  * Three apps had independently written a `MIN_PASSWORD_BYTES` constant into
6
6
  * their own `scripts/owner.ts`, and they had already drifted (9, 14, 14) with
7
7
  * a paragraph in each explaining itself against the others. A floor is a
8
8
  * POLICY, and a policy copied three times is three policies.
9
9
  *
10
- * The default is {@link DEFAULT_MIN_PASSWORD_BYTES} = 9, which is the floor the
11
- * owner wants for an ordinary satellite: long enough that it is not a PIN, short
12
- * enough that it does not push the owner toward writing it down or reusing one.
10
+ * The default is {@link DEFAULT_MIN_PASSWORD_BYTES} = 6 — the owner, 2026-09-24:
11
+ * *"make the minimum password length 6 characters"* (it was 9). It is a SIGN-IN
12
+ * floor: every door that uses it rate-limits guesses, so a short password costs
13
+ * an attacker attempts, not seconds. A secret that can be guessed OFFLINE (vault's
14
+ * passphrase, which derives its encryption key) raises it at its own call site.
13
15
  * Argon2id — what every caller hashes with — is what actually carries the cost
14
16
  * of a guess here; these apps have exactly ONE principal and no enumerable user
15
17
  * list, so the marginal value of characters 10–14 is small and the friction is
@@ -25,7 +27,7 @@
25
27
  * {@link resolveMinPasswordBytes} takes an optional override and **refuses to
26
28
  * go below the default**. An app that genuinely runs at higher stakes says so
27
29
  * at its own call site, in one visible argument, with a comment saying why.
28
- * No app overrides it today — the retired orch companion app did (14, as the single
30
+ * `vault` does (9, since 2026-09-24 — its passphrase is an encryption key). The retired orch companion app did (14, as the single
29
31
  * internet-facing door into the host that runs `claude` in every repo) until
30
32
  * the owner dropped it to the shared floor on 2026-07-26.
31
33
  *
@@ -38,12 +40,12 @@
38
40
  * they read, so a multi-byte character counts as more than one, which is the
39
41
  * conservative direction).
40
42
  */
41
- export const DEFAULT_MIN_PASSWORD_BYTES = 9;
43
+ export const DEFAULT_MIN_PASSWORD_BYTES = 6;
42
44
  /**
43
45
  * The floor this app enforces: the default, or a higher one it asks for.
44
46
  *
45
47
  * Throws on an override below the default rather than silently clamping. A
46
- * caller passing 6 believes it is enforcing 6; being handed 9 without a word is
48
+ * caller passing 4 believes it is enforcing 4; being handed 6 without a word is
47
49
  * how a security floor becomes folklore.
48
50
  */
49
51
  export function resolveMinPasswordBytes(override) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt-core",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "Framework-agnostic core of the cursedbelt split — isomorphic domain logic. cwip below it, cursedbelt-server and cursedbelt (react) above it.",
@@ -7,13 +7,13 @@ import { DEFAULT_MIN_PASSWORD_BYTES, resolveMinPasswordBytes } from './passwordP
7
7
  describe('resolveMinPasswordBytes', () => {
8
8
  it('is the shared default when an app asks for nothing', () => {
9
9
  expect(resolveMinPasswordBytes()).toBe(DEFAULT_MIN_PASSWORD_BYTES);
10
- expect(DEFAULT_MIN_PASSWORD_BYTES).toBe(9);
10
+ expect(DEFAULT_MIN_PASSWORD_BYTES).toBe(6);
11
11
  });
12
12
  it('lets an app raise it, visibly, at its own call site', () => {
13
13
  expect(resolveMinPasswordBytes(14)).toBe(14);
14
14
  });
15
15
  it('🔴 refuses to go BELOW the default, and refuses a non-integer', () => {
16
- expect(() => resolveMinPasswordBytes(8)).toThrow(/may only be RAISED/);
17
- expect(() => resolveMinPasswordBytes(9.5)).toThrow(/must be an integer/);
16
+ expect(() => resolveMinPasswordBytes(5)).toThrow(/may only be RAISED/);
17
+ expect(() => resolveMinPasswordBytes(6.5)).toThrow(/must be an integer/);
18
18
  });
19
19
  });
@@ -1,15 +1,17 @@
1
1
  /**
2
2
  * The one place a satellite's owner-password floor is decided.
3
3
  *
4
- * ── Why this is shared, and why the default is 9 ────────────────────────────
4
+ * ── Why this is shared, and why the default is 6 ────────────────────────────
5
5
  * Three apps had independently written a `MIN_PASSWORD_BYTES` constant into
6
6
  * their own `scripts/owner.ts`, and they had already drifted (9, 14, 14) with
7
7
  * a paragraph in each explaining itself against the others. A floor is a
8
8
  * POLICY, and a policy copied three times is three policies.
9
9
  *
10
- * The default is {@link DEFAULT_MIN_PASSWORD_BYTES} = 9, which is the floor the
11
- * owner wants for an ordinary satellite: long enough that it is not a PIN, short
12
- * enough that it does not push the owner toward writing it down or reusing one.
10
+ * The default is {@link DEFAULT_MIN_PASSWORD_BYTES} = 6 — the owner, 2026-09-24:
11
+ * *"make the minimum password length 6 characters"* (it was 9). It is a SIGN-IN
12
+ * floor: every door that uses it rate-limits guesses, so a short password costs
13
+ * an attacker attempts, not seconds. A secret that can be guessed OFFLINE (vault's
14
+ * passphrase, which derives its encryption key) raises it at its own call site.
13
15
  * Argon2id — what every caller hashes with — is what actually carries the cost
14
16
  * of a guess here; these apps have exactly ONE principal and no enumerable user
15
17
  * list, so the marginal value of characters 10–14 is small and the friction is
@@ -25,7 +27,7 @@
25
27
  * {@link resolveMinPasswordBytes} takes an optional override and **refuses to
26
28
  * go below the default**. An app that genuinely runs at higher stakes says so
27
29
  * at its own call site, in one visible argument, with a comment saying why.
28
- * No app overrides it today — the retired orch companion app did (14, as the single
30
+ * `vault` does (9, since 2026-09-24 — its passphrase is an encryption key). The retired orch companion app did (14, as the single
29
31
  * internet-facing door into the host that runs `claude` in every repo) until
30
32
  * the owner dropped it to the shared floor on 2026-07-26.
31
33
  *
@@ -39,13 +41,13 @@
39
41
  * they read, so a multi-byte character counts as more than one, which is the
40
42
  * conservative direction).
41
43
  */
42
- export const DEFAULT_MIN_PASSWORD_BYTES = 9;
44
+ export const DEFAULT_MIN_PASSWORD_BYTES = 6;
43
45
 
44
46
  /**
45
47
  * The floor this app enforces: the default, or a higher one it asks for.
46
48
  *
47
49
  * Throws on an override below the default rather than silently clamping. A
48
- * caller passing 6 believes it is enforcing 6; being handed 9 without a word is
50
+ * caller passing 4 believes it is enforcing 4; being handed 6 without a word is
49
51
  * how a security floor becomes folklore.
50
52
  */
51
53
  export function resolveMinPasswordBytes(override?: number): number {