@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.
- package/README.md +83 -3
- package/dist/cli/polly.js +21 -1
- package/dist/cli/polly.js.map +3 -3
- package/dist/src/background/index.js.map +7 -7
- package/dist/src/background/message-router.js.map +7 -7
- package/dist/src/elysia/index.d.ts +2 -0
- package/dist/src/elysia/index.js +177 -17
- package/dist/src/elysia/index.js.map +8 -5
- package/dist/src/elysia/peer-repo-plugin.d.ts +79 -0
- package/dist/src/elysia/signaling-server-plugin.d.ts +121 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +90 -1
- package/dist/src/index.js.map +15 -13
- package/dist/src/mesh.d.ts +29 -0
- package/dist/src/mesh.js +1502 -0
- package/dist/src/mesh.js.map +22 -0
- package/dist/src/peer.d.ts +29 -0
- package/dist/src/peer.js +928 -0
- package/dist/src/peer.js.map +20 -0
- package/dist/src/shared/adapters/index.js.map +6 -6
- package/dist/src/shared/lib/_client-only.d.ts +38 -0
- package/dist/src/shared/lib/access.d.ts +124 -0
- package/dist/src/shared/lib/blob-ref.d.ts +72 -0
- package/dist/src/shared/lib/context-helpers.js.map +7 -7
- package/dist/src/shared/lib/crdt-specialised.d.ts +129 -0
- package/dist/src/shared/lib/crdt-state.d.ts +86 -0
- package/dist/src/shared/lib/encryption.d.ts +117 -0
- package/dist/src/shared/lib/mesh-network-adapter.d.ts +130 -0
- package/dist/src/shared/lib/mesh-signaling-client.d.ts +85 -0
- package/dist/src/shared/lib/mesh-state.d.ts +102 -0
- package/dist/src/shared/lib/mesh-webrtc-adapter.d.ts +132 -0
- package/dist/src/shared/lib/message-bus.js.map +7 -7
- package/dist/src/shared/lib/migrate-primitive.d.ts +100 -0
- package/dist/src/shared/lib/pairing.d.ts +170 -0
- package/dist/src/shared/lib/peer-relay-adapter.d.ts +80 -0
- package/dist/src/shared/lib/peer-repo-server.d.ts +83 -0
- package/dist/src/shared/lib/peer-state.d.ts +117 -0
- package/dist/src/shared/lib/primitive-registry.d.ts +88 -0
- package/dist/src/shared/lib/resource.js.map +4 -4
- package/dist/src/shared/lib/revocation.d.ts +126 -0
- package/dist/src/shared/lib/schema-version.d.ts +129 -0
- package/dist/src/shared/lib/signing.d.ts +118 -0
- package/dist/src/shared/lib/state.js.map +4 -4
- package/dist/src/shared/state/app-state.js.map +5 -5
- package/dist/tools/init/src/cli.js.map +1 -1
- package/dist/tools/quality/src/cli.js +162 -0
- package/dist/tools/quality/src/cli.js.map +11 -0
- package/dist/tools/test/src/adapters/index.js.map +2 -2
- package/dist/tools/test/src/browser/harness.d.ts +80 -0
- package/dist/tools/test/src/browser/index.d.ts +32 -0
- package/dist/tools/test/src/browser/index.js +243 -0
- package/dist/tools/test/src/browser/index.js.map +10 -0
- package/dist/tools/test/src/browser/run.d.ts +26 -0
- package/dist/tools/test/src/index.js.map +2 -2
- package/dist/tools/verify/specs/tla/MeshState.cfg +21 -0
- package/dist/tools/verify/specs/tla/MeshState.tla +247 -0
- package/dist/tools/verify/specs/tla/PeerState.cfg +27 -0
- package/dist/tools/verify/specs/tla/PeerState.tla +238 -0
- package/dist/tools/verify/specs/tla/README.md +27 -3
- package/dist/tools/verify/src/cli.js.map +8 -8
- package/dist/tools/visualize/src/cli.js.map +7 -7
- 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>;
|