@peerbit/blocks-interface 2.1.7 → 2.2.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 CHANGED
@@ -13,3 +13,23 @@ consumer boundary, after the bytes are authenticated.
13
13
  DAG-CBOR block can still allocate its decoded object graph, so callers handling
14
14
  attacker-selected CIDs should prefer `verifyBlockBytes` unless they explicitly
15
15
  need the logical value and enforce suitable resource bounds.
16
+
17
+ ## Reclamation capability
18
+
19
+ `Blocks.localReclamation` is an operational capability, not caller-declared
20
+ metadata. A service may report `enforcedReclamation: "scoped-references-v1"`
21
+ through the additive `observedLocalStoreSafety` property only when that
22
+ capability exists; callers must additionally require a `ready` health result.
23
+ The existing `localStoreSafety` property and `BlockStoreSafety` declaration
24
+ type remain restricted to `enforcedReclamation: "none"` for source
25
+ compatibility. `DeclaredBlockStoreSafety` is an explicit alias, while
26
+ `ObservedBlockStoreSafety` includes the service-minted enforced variant.
27
+ Custom-store configuration therefore cannot assert an enforcement mechanism it
28
+ does not implement. Peerbit's enforced metadata value is private to the
29
+ built-in wrapper and is derived from that wrapper's actual capability; neither
30
+ the opt-in flag nor caller metadata can mint it.
31
+
32
+ Each `openScope` key is exactly 32 bytes and is defensively copied. Scope
33
+ handles belong to one service lifecycle. Managed retain/release operations are
34
+ single-block, bounded, idempotent, local-only, and isolated from raw `put`/`rm`
35
+ blocks.
@@ -17,7 +17,116 @@ export type CrashSafeBlockDurability = {
17
17
  readonly crashSafe: true;
18
18
  barrier(): MaybePromise<void>;
19
19
  };
20
+ /**
21
+ * Scope across which local references to a content-addressed block may alias.
22
+ *
23
+ * `block-service` is the scope of Peerbit's built-in stores: the backing
24
+ * namespace belongs to one blocks service, but every program using that
25
+ * service shares it. `caller-exclusive` is an explicit assertion that the
26
+ * declaring caller controls the entire physical namespace and every reference
27
+ * in it. `shared` means references may exist outside this block service;
28
+ * `unknown` makes no reliable scope assertion. Neither persistence nor a
29
+ * backend class implies any scope.
30
+ */
31
+ export type BlockStoreReferenceDomain = "block-service" | "caller-exclusive" | "shared" | "unknown";
32
+ /**
33
+ * Immutable facts needed before a caller considers physical block deletion.
34
+ *
35
+ * `enforcedReclamation: "none"` means the store exposes no reference-safe
36
+ * lease, fencing, atomic delete-if-unreferenced, or isolated-namespace
37
+ * primitive. A raw `rm` is therefore safe only for an authority that controls
38
+ * the complete reference domain. This field is deliberately separate from
39
+ * `persisted()`.
40
+ */
41
+ export type BlockStoreSafety = Readonly<{
42
+ referenceDomain: BlockStoreReferenceDomain;
43
+ enforcedReclamation: "none";
44
+ }>;
45
+ /** Explicit alias for APIs that accept caller-declared safety facts. */
46
+ export type DeclaredBlockStoreSafety = BlockStoreSafety;
47
+ /**
48
+ * Observed service safety. The enforced variant is valid only together with a
49
+ * matching, ready `Blocks.localReclamation` capability; metadata alone never
50
+ * grants deletion authority.
51
+ */
52
+ export type ObservedBlockStoreSafety = BlockStoreSafety | Readonly<{
53
+ referenceDomain: "block-service";
54
+ enforcedReclamation: "scoped-references-v1";
55
+ }>;
56
+ export type ScopedBlockReclamationLimits = Readonly<{
57
+ maxBlockBytes: number;
58
+ maxCidBytes: number;
59
+ scopeKeyBytes: number;
60
+ maxReferencesPerBlock: number;
61
+ maxPendingOperations: number;
62
+ maxPendingBytes: number;
63
+ }>;
64
+ export type ScopedBlockReclamationFaultCode = "ambiguous-mutation" | "corrupt-state" | "storage-failure";
65
+ export type ScopedBlockReclamationHealth = Readonly<{
66
+ status: "opening" | "ready" | "closed";
67
+ }> | Readonly<{
68
+ status: "faulted";
69
+ reason: ScopedBlockReclamationFaultCode;
70
+ }>;
71
+ export type ScopedBlockReleaseResult = "not-retained" | "retained" | "reclaimed";
72
+ /**
73
+ * One durable ownership scope inside a block-service managed namespace.
74
+ *
75
+ * A scope key is local authority, not a network identity. Callers must use a
76
+ * stable, collision-resistant value under their control; this mechanism does
77
+ * not isolate mutually hostile code that can invoke `openScope` with another
78
+ * caller's key. `retain` copies and CID-verifies bytes before publishing the
79
+ * reference. `release` can delete only managed bytes after the last durable
80
+ * scope reference is gone. Calls are idempotent and deliberately single-block
81
+ * so each unit of work is bounded.
82
+ */
83
+ export interface ScopedBlockReclamationScopeV1 {
84
+ put(bytes: Uint8Array): MaybePromise<string>;
85
+ retain(cid: string, bytes: Uint8Array): MaybePromise<string>;
86
+ release(cid: string): MaybePromise<ScopedBlockReleaseResult>;
87
+ }
88
+ /**
89
+ * Opt-in, local-only reference enforcement for a block-service-owned managed
90
+ * namespace. It never adopts or deletes blocks written through the legacy/raw
91
+ * `Blocks.put`/`Blocks.rm` namespace.
92
+ */
93
+ export interface ScopedBlockReclamationV1 {
94
+ readonly kind: "scoped-references-v1";
95
+ readonly limits: ScopedBlockReclamationLimits;
96
+ health(): ScopedBlockReclamationHealth;
97
+ openScope(scopeKey: Uint8Array): ScopedBlockReclamationScopeV1;
98
+ }
99
+ export declare const UNKNOWN_BLOCK_STORE_SAFETY: BlockStoreSafety;
100
+ export declare const BLOCK_SERVICE_BLOCK_STORE_SAFETY: BlockStoreSafety;
101
+ /**
102
+ * Validate, defensively copy, and freeze block-store safety metadata.
103
+ *
104
+ * The input is intentionally `unknown`: declarations can cross JavaScript and
105
+ * configuration boundaries where TypeScript's static shape is unavailable.
106
+ */
107
+ export declare const normalizeBlockStoreSafety: (value: unknown) => BlockStoreSafety;
20
108
  export interface Blocks extends WaitForPeer {
109
+ /**
110
+ * Legacy caller-declared safety metadata for this service's local physical
111
+ * block namespace. Its type and values remain restricted to
112
+ * `enforcedReclamation: "none"`.
113
+ */
114
+ readonly localStoreSafety?: BlockStoreSafety;
115
+ /**
116
+ * Optional service-observed safety metadata. Absence is equivalent to
117
+ * `localStoreSafety` (or {@link UNKNOWN_BLOCK_STORE_SAFETY} when both are
118
+ * absent), so older and custom implementations fail closed.
119
+ *
120
+ * The enforced variant is descriptive only; callers must also require the
121
+ * matching, ready `localReclamation` capability.
122
+ */
123
+ readonly observedLocalStoreSafety?: ObservedBlockStoreSafety;
124
+ /**
125
+ * Present only when this exact service owns and enforces a separate managed
126
+ * namespace. Callers must require `health().status === "ready"`; metadata
127
+ * alone is not authority to delete.
128
+ */
129
+ readonly localReclamation?: ScopedBlockReclamationV1;
21
130
  put(data: Uint8Array | {
22
131
  block: Block<any, any, any, any>;
23
132
  cid: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/dist/src/index.js CHANGED
@@ -1,4 +1,41 @@
1
1
  import {} from "@peerbit/stream-interface";
2
2
  import {} from "multiformats/block";
3
+ export const UNKNOWN_BLOCK_STORE_SAFETY = Object.freeze({
4
+ referenceDomain: "unknown",
5
+ enforcedReclamation: "none",
6
+ });
7
+ export const BLOCK_SERVICE_BLOCK_STORE_SAFETY = Object.freeze({
8
+ referenceDomain: "block-service",
9
+ enforcedReclamation: "none",
10
+ });
11
+ /**
12
+ * Validate, defensively copy, and freeze block-store safety metadata.
13
+ *
14
+ * The input is intentionally `unknown`: declarations can cross JavaScript and
15
+ * configuration boundaries where TypeScript's static shape is unavailable.
16
+ */
17
+ export const normalizeBlockStoreSafety = (value) => {
18
+ if (value === undefined)
19
+ return UNKNOWN_BLOCK_STORE_SAFETY;
20
+ if (value === null || typeof value !== "object") {
21
+ throw new TypeError("Invalid block-store safety metadata");
22
+ }
23
+ const referenceDomain = value
24
+ .referenceDomain;
25
+ const enforcedReclamation = value
26
+ .enforcedReclamation;
27
+ if (referenceDomain !== "block-service" &&
28
+ referenceDomain !== "caller-exclusive" &&
29
+ referenceDomain !== "shared" &&
30
+ referenceDomain !== "unknown") {
31
+ throw new TypeError("Invalid block-store reference domain");
32
+ }
33
+ // Enforced reclamation is an operational capability, not a caller assertion.
34
+ // DirectBlock mints its scoped capability only for its own supported store.
35
+ if (enforcedReclamation !== "none") {
36
+ throw new TypeError("Unsupported block-store reclamation capability");
37
+ }
38
+ return Object.freeze({ referenceDomain, enforcedReclamation });
39
+ };
3
40
  export { cidifyString, stringifyCid, createBlock, getBlockValue, calculateRawCid, checkDecodeBlock, verifyBlockBytes, codecCodes, defaultHasher, codecMap, } from "./block.js";
4
41
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAc,MAAM,oBAAoB,CAAC;AAgEhD,OAAO,EACN,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,QAAQ,GACR,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAc,MAAM,oBAAoB,CAAC;AA4HhD,MAAM,CAAC,MAAM,0BAA0B,GAAqB,MAAM,CAAC,MAAM,CAAC;IACzE,eAAe,EAAE,SAAS;IAC1B,mBAAmB,EAAE,MAAM;CAC3B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gCAAgC,GAAqB,MAAM,CAAC,MAAM,CAC9E;IACC,eAAe,EAAE,eAAe;IAChC,mBAAmB,EAAE,MAAM;CAC3B,CACD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACxC,KAAc,EACK,EAAE;IACrB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,0BAA0B,CAAC;IAC3D,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACjD,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,eAAe,GAAI,KAAuC;SAC9D,eAAe,CAAC;IAClB,MAAM,mBAAmB,GAAI,KAA2C;SACtE,mBAAmB,CAAC;IACtB,IACC,eAAe,KAAK,eAAe;QACnC,eAAe,KAAK,kBAAkB;QACtC,eAAe,KAAK,QAAQ;QAC5B,eAAe,KAAK,SAAS,EAC5B,CAAC;QACF,MAAM,IAAI,SAAS,CAAC,sCAAsC,CAAC,CAAC;IAC7D,CAAC;IACD,6EAA6E;IAC7E,4EAA4E;IAC5E,IAAI,mBAAmB,KAAK,MAAM,EAAE,CAAC;QACpC,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAChE,CAAC,CAAC;AAgEF,OAAO,EACN,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,QAAQ,GACR,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peerbit/blocks-interface",
3
- "version": "2.1.7",
3
+ "version": "2.2.0",
4
4
  "description": "Block store streaming",
5
5
  "type": "module",
6
6
  "sideEffects": false,
package/src/index.ts CHANGED
@@ -22,7 +22,174 @@ export type CrashSafeBlockDurability = {
22
22
  barrier(): MaybePromise<void>;
23
23
  };
24
24
 
25
+ /**
26
+ * Scope across which local references to a content-addressed block may alias.
27
+ *
28
+ * `block-service` is the scope of Peerbit's built-in stores: the backing
29
+ * namespace belongs to one blocks service, but every program using that
30
+ * service shares it. `caller-exclusive` is an explicit assertion that the
31
+ * declaring caller controls the entire physical namespace and every reference
32
+ * in it. `shared` means references may exist outside this block service;
33
+ * `unknown` makes no reliable scope assertion. Neither persistence nor a
34
+ * backend class implies any scope.
35
+ */
36
+ export type BlockStoreReferenceDomain =
37
+ | "block-service"
38
+ | "caller-exclusive"
39
+ | "shared"
40
+ | "unknown";
41
+
42
+ /**
43
+ * Immutable facts needed before a caller considers physical block deletion.
44
+ *
45
+ * `enforcedReclamation: "none"` means the store exposes no reference-safe
46
+ * lease, fencing, atomic delete-if-unreferenced, or isolated-namespace
47
+ * primitive. A raw `rm` is therefore safe only for an authority that controls
48
+ * the complete reference domain. This field is deliberately separate from
49
+ * `persisted()`.
50
+ */
51
+ export type BlockStoreSafety = Readonly<{
52
+ referenceDomain: BlockStoreReferenceDomain;
53
+ enforcedReclamation: "none";
54
+ }>;
55
+
56
+ /** Explicit alias for APIs that accept caller-declared safety facts. */
57
+ export type DeclaredBlockStoreSafety = BlockStoreSafety;
58
+
59
+ /**
60
+ * Observed service safety. The enforced variant is valid only together with a
61
+ * matching, ready `Blocks.localReclamation` capability; metadata alone never
62
+ * grants deletion authority.
63
+ */
64
+ export type ObservedBlockStoreSafety =
65
+ | BlockStoreSafety
66
+ | Readonly<{
67
+ referenceDomain: "block-service";
68
+ enforcedReclamation: "scoped-references-v1";
69
+ }>;
70
+
71
+ export type ScopedBlockReclamationLimits = Readonly<{
72
+ maxBlockBytes: number;
73
+ maxCidBytes: number;
74
+ scopeKeyBytes: number;
75
+ maxReferencesPerBlock: number;
76
+ maxPendingOperations: number;
77
+ maxPendingBytes: number;
78
+ }>;
79
+
80
+ export type ScopedBlockReclamationFaultCode =
81
+ | "ambiguous-mutation"
82
+ | "corrupt-state"
83
+ | "storage-failure";
84
+
85
+ export type ScopedBlockReclamationHealth =
86
+ | Readonly<{ status: "opening" | "ready" | "closed" }>
87
+ | Readonly<{
88
+ status: "faulted";
89
+ reason: ScopedBlockReclamationFaultCode;
90
+ }>;
91
+
92
+ export type ScopedBlockReleaseResult =
93
+ | "not-retained"
94
+ | "retained"
95
+ | "reclaimed";
96
+
97
+ /**
98
+ * One durable ownership scope inside a block-service managed namespace.
99
+ *
100
+ * A scope key is local authority, not a network identity. Callers must use a
101
+ * stable, collision-resistant value under their control; this mechanism does
102
+ * not isolate mutually hostile code that can invoke `openScope` with another
103
+ * caller's key. `retain` copies and CID-verifies bytes before publishing the
104
+ * reference. `release` can delete only managed bytes after the last durable
105
+ * scope reference is gone. Calls are idempotent and deliberately single-block
106
+ * so each unit of work is bounded.
107
+ */
108
+ export interface ScopedBlockReclamationScopeV1 {
109
+ put(bytes: Uint8Array): MaybePromise<string>;
110
+ retain(cid: string, bytes: Uint8Array): MaybePromise<string>;
111
+ release(cid: string): MaybePromise<ScopedBlockReleaseResult>;
112
+ }
113
+
114
+ /**
115
+ * Opt-in, local-only reference enforcement for a block-service-owned managed
116
+ * namespace. It never adopts or deletes blocks written through the legacy/raw
117
+ * `Blocks.put`/`Blocks.rm` namespace.
118
+ */
119
+ export interface ScopedBlockReclamationV1 {
120
+ readonly kind: "scoped-references-v1";
121
+ readonly limits: ScopedBlockReclamationLimits;
122
+ health(): ScopedBlockReclamationHealth;
123
+ openScope(scopeKey: Uint8Array): ScopedBlockReclamationScopeV1;
124
+ }
125
+
126
+ export const UNKNOWN_BLOCK_STORE_SAFETY: BlockStoreSafety = Object.freeze({
127
+ referenceDomain: "unknown",
128
+ enforcedReclamation: "none",
129
+ });
130
+
131
+ export const BLOCK_SERVICE_BLOCK_STORE_SAFETY: BlockStoreSafety = Object.freeze(
132
+ {
133
+ referenceDomain: "block-service",
134
+ enforcedReclamation: "none",
135
+ },
136
+ );
137
+
138
+ /**
139
+ * Validate, defensively copy, and freeze block-store safety metadata.
140
+ *
141
+ * The input is intentionally `unknown`: declarations can cross JavaScript and
142
+ * configuration boundaries where TypeScript's static shape is unavailable.
143
+ */
144
+ export const normalizeBlockStoreSafety = (
145
+ value: unknown,
146
+ ): BlockStoreSafety => {
147
+ if (value === undefined) return UNKNOWN_BLOCK_STORE_SAFETY;
148
+ if (value === null || typeof value !== "object") {
149
+ throw new TypeError("Invalid block-store safety metadata");
150
+ }
151
+ const referenceDomain = (value as { referenceDomain?: unknown })
152
+ .referenceDomain;
153
+ const enforcedReclamation = (value as { enforcedReclamation?: unknown })
154
+ .enforcedReclamation;
155
+ if (
156
+ referenceDomain !== "block-service" &&
157
+ referenceDomain !== "caller-exclusive" &&
158
+ referenceDomain !== "shared" &&
159
+ referenceDomain !== "unknown"
160
+ ) {
161
+ throw new TypeError("Invalid block-store reference domain");
162
+ }
163
+ // Enforced reclamation is an operational capability, not a caller assertion.
164
+ // DirectBlock mints its scoped capability only for its own supported store.
165
+ if (enforcedReclamation !== "none") {
166
+ throw new TypeError("Unsupported block-store reclamation capability");
167
+ }
168
+ return Object.freeze({ referenceDomain, enforcedReclamation });
169
+ };
170
+
25
171
  export interface Blocks extends WaitForPeer {
172
+ /**
173
+ * Legacy caller-declared safety metadata for this service's local physical
174
+ * block namespace. Its type and values remain restricted to
175
+ * `enforcedReclamation: "none"`.
176
+ */
177
+ readonly localStoreSafety?: BlockStoreSafety;
178
+ /**
179
+ * Optional service-observed safety metadata. Absence is equivalent to
180
+ * `localStoreSafety` (or {@link UNKNOWN_BLOCK_STORE_SAFETY} when both are
181
+ * absent), so older and custom implementations fail closed.
182
+ *
183
+ * The enforced variant is descriptive only; callers must also require the
184
+ * matching, ready `localReclamation` capability.
185
+ */
186
+ readonly observedLocalStoreSafety?: ObservedBlockStoreSafety;
187
+ /**
188
+ * Present only when this exact service owns and enforces a separate managed
189
+ * namespace. Callers must require `health().status === "ready"`; metadata
190
+ * alone is not authority to delete.
191
+ */
192
+ readonly localReclamation?: ScopedBlockReclamationV1;
26
193
  put(
27
194
  data: Uint8Array | { block: Block<any, any, any, any>; cid: string },
28
195
  ): MaybePromise<string>;