@fairfox/polly 0.20.1 → 0.22.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.
Files changed (62) hide show
  1. package/README.md +83 -3
  2. package/dist/cli/polly.js +21 -1
  3. package/dist/cli/polly.js.map +3 -3
  4. package/dist/src/background/index.js.map +7 -7
  5. package/dist/src/background/message-router.js.map +7 -7
  6. package/dist/src/elysia/index.d.ts +2 -0
  7. package/dist/src/elysia/index.js +177 -17
  8. package/dist/src/elysia/index.js.map +8 -5
  9. package/dist/src/elysia/peer-repo-plugin.d.ts +79 -0
  10. package/dist/src/elysia/signaling-server-plugin.d.ts +121 -0
  11. package/dist/src/index.d.ts +4 -0
  12. package/dist/src/index.js +90 -1
  13. package/dist/src/index.js.map +15 -13
  14. package/dist/src/mesh.d.ts +29 -0
  15. package/dist/src/mesh.js +1502 -0
  16. package/dist/src/mesh.js.map +22 -0
  17. package/dist/src/peer.d.ts +29 -0
  18. package/dist/src/peer.js +928 -0
  19. package/dist/src/peer.js.map +20 -0
  20. package/dist/src/shared/adapters/index.js.map +6 -6
  21. package/dist/src/shared/lib/_client-only.d.ts +38 -0
  22. package/dist/src/shared/lib/access.d.ts +124 -0
  23. package/dist/src/shared/lib/blob-ref.d.ts +72 -0
  24. package/dist/src/shared/lib/context-helpers.js.map +7 -7
  25. package/dist/src/shared/lib/crdt-specialised.d.ts +129 -0
  26. package/dist/src/shared/lib/crdt-state.d.ts +86 -0
  27. package/dist/src/shared/lib/encryption.d.ts +117 -0
  28. package/dist/src/shared/lib/mesh-network-adapter.d.ts +130 -0
  29. package/dist/src/shared/lib/mesh-signaling-client.d.ts +85 -0
  30. package/dist/src/shared/lib/mesh-state.d.ts +102 -0
  31. package/dist/src/shared/lib/mesh-webrtc-adapter.d.ts +132 -0
  32. package/dist/src/shared/lib/message-bus.js.map +7 -7
  33. package/dist/src/shared/lib/migrate-primitive.d.ts +100 -0
  34. package/dist/src/shared/lib/pairing.d.ts +170 -0
  35. package/dist/src/shared/lib/peer-relay-adapter.d.ts +80 -0
  36. package/dist/src/shared/lib/peer-repo-server.d.ts +83 -0
  37. package/dist/src/shared/lib/peer-state.d.ts +117 -0
  38. package/dist/src/shared/lib/primitive-registry.d.ts +88 -0
  39. package/dist/src/shared/lib/resource.js.map +4 -4
  40. package/dist/src/shared/lib/revocation.d.ts +126 -0
  41. package/dist/src/shared/lib/schema-version.d.ts +129 -0
  42. package/dist/src/shared/lib/signing.d.ts +118 -0
  43. package/dist/src/shared/lib/state.js.map +4 -4
  44. package/dist/src/shared/state/app-state.js.map +5 -5
  45. package/dist/tools/init/src/cli.js.map +1 -1
  46. package/dist/tools/quality/src/cli.js +162 -0
  47. package/dist/tools/quality/src/cli.js.map +11 -0
  48. package/dist/tools/test/src/adapters/index.js.map +2 -2
  49. package/dist/tools/test/src/browser/harness.d.ts +80 -0
  50. package/dist/tools/test/src/browser/index.d.ts +32 -0
  51. package/dist/tools/test/src/browser/index.js +243 -0
  52. package/dist/tools/test/src/browser/index.js.map +10 -0
  53. package/dist/tools/test/src/browser/run.d.ts +26 -0
  54. package/dist/tools/test/src/index.js.map +2 -2
  55. package/dist/tools/verify/specs/tla/MeshState.cfg +21 -0
  56. package/dist/tools/verify/specs/tla/MeshState.tla +247 -0
  57. package/dist/tools/verify/specs/tla/PeerState.cfg +27 -0
  58. package/dist/tools/verify/specs/tla/PeerState.tla +238 -0
  59. package/dist/tools/verify/specs/tla/README.md +27 -3
  60. package/dist/tools/verify/src/cli.js.map +8 -8
  61. package/dist/tools/visualize/src/cli.js.map +7 -7
  62. package/package.json +51 -5
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Access — declarative read/write authorisation for Polly's peer-first primitives.
3
+ *
4
+ * The new $peerState and $meshState primitives ship with a declarative `access`
5
+ * option that compiles to server share policies ($peerState), signed-op access sets
6
+ * ($meshState), or both when $peerState opts in via `sign: true`. Application code
7
+ * expresses "who can read" and "who can write" as a pair of predicates over an
8
+ * authenticated peer identity, and Polly enforces the predicates uniformly at every
9
+ * transport and storage boundary.
10
+ *
11
+ * This module defines the types and a small set of primitive factories and
12
+ * compositors. Primitive constructors in Phase 1 and Phase 2 will consume the
13
+ * {@link Access} shape; the per-primitive "what does this compile to" resolution
14
+ * lives in those constructors rather than here, because the target varies by
15
+ * transport.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { $peerState } from "@fairfox/polly";
20
+ * import { ownerAccess } from "@/shared/lib/access";
21
+ *
22
+ * const notes = $peerState("notes", defaults, {
23
+ * access: ownerAccess("peer-abc123"),
24
+ * });
25
+ * ```
26
+ */
27
+ /**
28
+ * An authenticated peer's identity as seen by Polly's authorisation layer.
29
+ *
30
+ * The shape is intentionally minimal: a stable {@link peerId} plus an optional
31
+ * metadata bag that the transport's authentication hook can populate with
32
+ * whatever it knows about the peer (session user id, device type, group
33
+ * memberships, signing public key, etc.). Applications that need stronger
34
+ * typing can parameterise {@link Access} on a narrower identity type.
35
+ */
36
+ export interface PeerIdentity {
37
+ /** Stable identifier for this peer. Must be unique within the application. */
38
+ peerId: string;
39
+ /**
40
+ * Transport-specific metadata attached by the authentication layer. For
41
+ * $peerState this is usually session data from the Elysia auth hook; for
42
+ * $meshState this is usually the peer's verified signing public key and any
43
+ * group memberships derived from it.
44
+ */
45
+ metadata?: Record<string, unknown>;
46
+ }
47
+ /**
48
+ * A predicate over peer identities. Returns true if the identity satisfies the
49
+ * access condition, false otherwise. Predicates must be pure — the same input
50
+ * produces the same output — so that Polly can cache authorisation decisions
51
+ * and reason about them in TLA+.
52
+ */
53
+ export type AccessPredicate<Identity = PeerIdentity> = (identity: Identity) => boolean;
54
+ /**
55
+ * Declarative read/write access for a single logical document. Every Polly
56
+ * peer-first primitive that accepts an `access` option expects this shape.
57
+ *
58
+ * Read and write are independent: a predicate that returns true for read does
59
+ * not imply anything about write. Applications that want "if you can write,
60
+ * you can read" express it explicitly, either by reusing the same predicate
61
+ * or by composing `read: or(readPred, writePred)`.
62
+ */
63
+ export interface Access<Identity = PeerIdentity> {
64
+ read: AccessPredicate<Identity>;
65
+ write: AccessPredicate<Identity>;
66
+ }
67
+ /**
68
+ * A predicate that accepts every identity. Useful for public documents and
69
+ * for the "read" half of write-gated-but-publicly-visible patterns.
70
+ */
71
+ export declare function anyone<Identity = PeerIdentity>(): AccessPredicate<Identity>;
72
+ /**
73
+ * A predicate that rejects every identity. Useful as an explicit "no-one can
74
+ * write to this" marker and as the identity element for `or`.
75
+ */
76
+ export declare function nobody<Identity = PeerIdentity>(): AccessPredicate<Identity>;
77
+ /**
78
+ * A predicate that accepts exactly one peer by id.
79
+ */
80
+ export declare function onlyPeer<Identity extends PeerIdentity = PeerIdentity>(peerId: string): AccessPredicate<Identity>;
81
+ /**
82
+ * A predicate that accepts any peer whose id is in the given set. The set is
83
+ * captured at factory time and not re-read, so mutating the input array after
84
+ * calling this has no effect on the returned predicate.
85
+ */
86
+ export declare function anyOfPeers<Identity extends PeerIdentity = PeerIdentity>(peerIds: readonly string[]): AccessPredicate<Identity>;
87
+ /**
88
+ * Logical AND of two predicates. Accepts an identity only if both inputs
89
+ * accept it. Short-circuits on the first false.
90
+ */
91
+ export declare function and<Identity>(a: AccessPredicate<Identity>, b: AccessPredicate<Identity>): AccessPredicate<Identity>;
92
+ /**
93
+ * Logical OR of two predicates. Accepts an identity if either input accepts
94
+ * it. Short-circuits on the first true.
95
+ */
96
+ export declare function or<Identity>(a: AccessPredicate<Identity>, b: AccessPredicate<Identity>): AccessPredicate<Identity>;
97
+ /**
98
+ * Logical NOT of a predicate.
99
+ */
100
+ export declare function not<Identity>(a: AccessPredicate<Identity>): AccessPredicate<Identity>;
101
+ /**
102
+ * Public read and write for every peer. The default for documents that are
103
+ * genuinely shared across everyone in the deployment. Not a sensible default
104
+ * for $meshState, where the signing layer expects a bounded access set.
105
+ */
106
+ export declare function publicAccess<Identity extends PeerIdentity = PeerIdentity>(): Access<Identity>;
107
+ /**
108
+ * Read and write restricted to a single owner peer. The strictest common
109
+ * shape: a personal-notes document, a single-user setting store, anything
110
+ * scoped to one device chain.
111
+ */
112
+ export declare function ownerAccess<Identity extends PeerIdentity = PeerIdentity>(peerId: string): Access<Identity>;
113
+ /**
114
+ * Read and write restricted to a bounded group of peers. Both halves use the
115
+ * same predicate, which is usually what groups want; applications that need
116
+ * "some can read, fewer can write" should construct {@link Access} directly.
117
+ */
118
+ export declare function groupAccess<Identity extends PeerIdentity = PeerIdentity>(peerIds: readonly string[]): Access<Identity>;
119
+ /**
120
+ * Everyone can read; only the supplied predicate can write. Common for
121
+ * broadcast-style documents where one peer (or a group) publishes and the
122
+ * rest observe.
123
+ */
124
+ export declare function readOnlyExcept<Identity extends PeerIdentity = PeerIdentity>(writer: AccessPredicate<Identity>): Access<Identity>;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * BlobRef — content-addressed reference to a binary blob.
3
+ *
4
+ * CRDT documents held by `$peerState` and `$meshState` primitives should not embed
5
+ * large binary payloads directly. The Automerge history grows monotonically with every
6
+ * op, and embedding a file means every op carries the file, memory explodes, and sync
7
+ * bandwidth is terrible. The sound pattern is to store a reference to the blob inside
8
+ * the document and keep the bytes in a separate, content-addressed blob store.
9
+ *
10
+ * This module defines the reference shape so that applications can hold `BlobRef`
11
+ * values inside their `$peerState`/`$meshState` documents from day one. The actual
12
+ * blob store, the upload/fetch API, and transport-specific blob sync are deliberately
13
+ * out of scope and will land in a follow-up RFC. Provisioning the type now prevents
14
+ * a data-model migration when that RFC ships.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const doc = $peerState<Document>("doc", { title: "", attachments: [] });
19
+ *
20
+ * const bytes = new Uint8Array(await file.arrayBuffer());
21
+ * const ref = await createBlobRef({
22
+ * bytes,
23
+ * filename: file.name,
24
+ * mimeType: file.type,
25
+ * });
26
+ *
27
+ * doc.value = {
28
+ * ...doc.value,
29
+ * attachments: [...doc.value.attachments, ref],
30
+ * };
31
+ * ```
32
+ */
33
+ /**
34
+ * Content-addressed reference to a binary blob.
35
+ *
36
+ * The `hash` field is a hex-encoded SHA-256 digest of the blob's bytes. Two blobs
37
+ * with identical bytes always produce the same hash, so references can be deduplicated
38
+ * and the blob store (when it ships) can use the hash as its primary key.
39
+ */
40
+ export type BlobRef = {
41
+ /** Hex-encoded SHA-256 digest of the blob's bytes (64 lowercase hex characters). */
42
+ hash: string;
43
+ /** Length of the blob in bytes. */
44
+ size: number;
45
+ /** Filename as supplied by the originating application. Not used for addressing. */
46
+ filename: string;
47
+ /** MIME type as supplied by the originating application. Not used for addressing. */
48
+ mimeType: string;
49
+ };
50
+ /**
51
+ * Type guard for {@link BlobRef}. Useful at CRDT document boundaries where values
52
+ * may have been authored by older clients or by clients running different schemas.
53
+ */
54
+ export declare function isBlobRef(value: unknown): value is BlobRef;
55
+ /**
56
+ * Compute the SHA-256 hex digest of a byte sequence. Pure and deterministic.
57
+ */
58
+ export declare function computeBlobHash(bytes: Uint8Array): Promise<string>;
59
+ /**
60
+ * Arguments for {@link createBlobRef}.
61
+ */
62
+ export type CreateBlobRefArgs = {
63
+ bytes: Uint8Array;
64
+ filename: string;
65
+ mimeType: string;
66
+ };
67
+ /**
68
+ * Build a {@link BlobRef} from raw bytes and metadata. The hash is computed from the
69
+ * bytes; the filename and mimeType are carried from the originating application
70
+ * verbatim and do not affect the content address.
71
+ */
72
+ export declare function createBlobRef({ bytes, filename, mimeType, }: CreateBlobRefArgs): Promise<BlobRef>;