@freqhole/haruspex 0.2.1 → 0.2.3

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 ADDED
@@ -0,0 +1,125 @@
1
+ # haruspex
2
+
3
+ everything auth for the freqhole world of apps: webauthn passkeys, knock access requests,
4
+ user identity with multi-device node ids, roles + groups, api keys + invite codes, an acl
5
+ evaluator, and the friendz peer protocol (presence, gossip, friend requests). rust crate
6
+ `haruspex` + npm package `@freqhole/haruspex`.
7
+
8
+ ## architecture
9
+
10
+ protocol logic is transport-agnostic: it takes (caller identity, message) and returns
11
+ responses. iroh p2p, http, or ipc bindings are thin shells around the same core. this is a
12
+ decentralized, peer-to-peer system - peers talk to peers; some are always-on, some ephemeral.
13
+
14
+ ```mermaid
15
+ graph LR
16
+ subgraph apps
17
+ A[your app + policy glue]
18
+ end
19
+ subgraph haruspex core
20
+ S[stores: identity / knock / friendz /<br/>groups / invites / credentials]
21
+ E[acl evaluator:<br/>role grants + live groups]
22
+ P[friendz protocol:<br/>dispatch + gossip + presence]
23
+ W[webauthn ceremonies<br/>+ ChallengeStore]
24
+ end
25
+ T1[iroh ProtocolHandler] --- P
26
+ T2[http / ipc / anything] --- P
27
+ A --> S & E & P & W
28
+ S --- DB[(haruspex.db<br/>own sqlite file)]
29
+ ```
30
+
31
+ - each library owns its OWN sqlite db file (`haruspex.db`) - never tables inside a host
32
+ app's db. cross-domain joins are an app concern (batch resolvers provided).
33
+ - apps extend the wire protocol with namespaced `AppExtension` messages (`myapp:thing`)
34
+ without forking this repo.
35
+
36
+ ## structure
37
+
38
+ ```
39
+ rust/ crate: haruspex
40
+ src/
41
+ identity/ users, device node ids, attestation
42
+ stores/ store traits + sqlite impls (identity, knock, friendz, groups, invites, credentials)
43
+ acl/ evaluator: role grants, live groups, resource ancestry, RoleResolver seam
44
+ knock/ knock lifecycle + KnockPolicy trait
45
+ webauthn/ ceremony handlers (feature: webauthn)
46
+ protocol/ friendz messages, codec, FriendzService, gossip; iroh shell (feature: iroh)
47
+ sqlite/ pool open/migrations
48
+ testing/ fixtures + fake stores (feature: test-utils)
49
+ examples/ runnable walkthroughs (see below)
50
+ fixtures/ committed protocol wire fixtures (shared with ts)
51
+ ts/ npm: @freqhole/haruspex
52
+ src/{identity,webauthn,knock,share,flows,protocol,permissions,state,solid,testing}
53
+ docs/ design notes specific to this repo
54
+ ```
55
+
56
+ ## rust: getting started
57
+
58
+ ```rust
59
+ use haruspex::stores::IdentityStore;
60
+ use haruspex::testing::{identity_store, open_in_memory};
61
+
62
+ let pool = open_in_memory().await; // or sqlite::open(path) in an app
63
+ let identities = identity_store(&pool);
64
+ let alice = identities.upsert_identity(/* Identity { .. } */).await?;
65
+ identities.add_device(/* DeviceNode { node_id, .. } */).await?;
66
+ ```
67
+
68
+ features: `webauthn` (passkey ceremonies), `iroh` (friendz ProtocolHandler), `test-utils`
69
+ (in-memory fixtures). default = none of them - the core is dependency-light.
70
+
71
+ examples (each runnable, each a tiny tour):
72
+
73
+ ```bash
74
+ cargo run --example identity-lifecycle --features test-utils # identity + devices + attestation
75
+ cargo run --example acl-roles --features test-utils # grants, groups, evaluator
76
+ cargo run --example role-backfill --features test-utils # legacy role column -> grants
77
+ cargo run --example knock-exchange --features test-utils # knock lifecycle + policy
78
+ cargo run --example two-peer-knock-iroh --features "iroh test-utils" # real iroh, two endpoints
79
+ ```
80
+
81
+ ## ts: getting started
82
+
83
+ framework-free core subpaths; `solid-js` is an optional peer dep used only by `./solid`.
84
+
85
+ | subpath | what |
86
+ | --------------- | ---------------------------------------------------------------------------- |
87
+ | `./identity` | P2PIdentity, idb store, cross-app resolution, web-locks leadership |
88
+ | `./webauthn` | credential codecs + transport-injected ceremony runners |
89
+ | `./knock` | knock requester/responder state machines over idb stores |
90
+ | `./share` | share-token codec + peer-address parsing/detection |
91
+ | `./flows` | headless add-peer FSM (send(event) -> effects) |
92
+ | `./protocol` | friendz zod schemas + codec + FriendzClient (fixture-validated against rust) |
93
+ | `./permissions` | role-hierarchy logic over an injected role table |
94
+ | `./state` | peer-names, endpoint-control (framework-free singletons) |
95
+ | `./solid` | solid-js components/signals (optional) |
96
+ | `./testing` | fixtures + fakes for consumer test suites |
97
+
98
+ ```ts
99
+ import {
100
+ resolveIdentity,
101
+ createIdbIdentityStore,
102
+ } from "@freqhole/haruspex/identity";
103
+ import { sendKnock, createIdbKnockStore } from "@freqhole/haruspex/knock";
104
+ // stores get their OWN idb database name - never your app's main db
105
+ ```
106
+
107
+ ## developer quick start
108
+
109
+ ```bash
110
+ # rust
111
+ cargo test --workspace --all-features
112
+ cargo fmt --all --check && cargo clippy --workspace --all-targets
113
+
114
+ # ts
115
+ cd ts && npm i
116
+ npm run typecheck && npm test && npm run build
117
+ ```
118
+
119
+ the crate owns its own sqlite db (`haruspex.db`); compiling needs no database (see
120
+ `rust/src/sqlite/mod.rs`). consumers today: tomb/grimoire (auth storage + evaluator),
121
+ tomb/spume (identity, webauthn), playlistz (knock, share), skein (friendz/peer stores) -
122
+ via path/git deps (rust) and `file:` deps (ts), no registry publishing yet.
123
+
124
+ see [docs/](docs/) for design notes; the canonical refactor plan lives in
125
+ tomb/docs/xl-refactor/.
@@ -94,12 +94,16 @@ declare const ProfileResponseSchema: z.ZodObject<{
94
94
  accentColor: z.ZodOptional<z.ZodNumber>;
95
95
  profileDocId: z.ZodOptional<z.ZodString>;
96
96
  profileUpdatedAt: z.ZodOptional<z.ZodString>;
97
+ isHub: z.ZodOptional<z.ZodBoolean>;
97
98
  }, z.core.$strip>;
98
99
  declare const FriendRequestSchema: z.ZodObject<{
99
100
  type: z.ZodLiteral<"friend-request">;
100
101
  v: z.ZodDefault<z.ZodNumber>;
101
102
  fromNodeId: z.ZodString;
102
103
  fromUsername: z.ZodString;
104
+ bio: z.ZodOptional<z.ZodString>;
105
+ avatarDataUrl: z.ZodOptional<z.ZodString>;
106
+ accentColor: z.ZodOptional<z.ZodNumber>;
103
107
  isHub: z.ZodOptional<z.ZodBoolean>;
104
108
  }, z.core.$strip>;
105
109
  declare const FriendAcceptSchema: z.ZodObject<{
@@ -107,6 +111,9 @@ declare const FriendAcceptSchema: z.ZodObject<{
107
111
  v: z.ZodDefault<z.ZodNumber>;
108
112
  fromNodeId: z.ZodString;
109
113
  fromUsername: z.ZodString;
114
+ bio: z.ZodOptional<z.ZodString>;
115
+ avatarDataUrl: z.ZodOptional<z.ZodString>;
116
+ accentColor: z.ZodOptional<z.ZodNumber>;
110
117
  isHub: z.ZodOptional<z.ZodBoolean>;
111
118
  }, z.core.$strip>;
112
119
  declare const FriendAcceptAckSchema: z.ZodObject<{
@@ -211,6 +218,8 @@ declare const IdentityUpdateSchema: z.ZodObject<{
211
218
  nodeId: z.ZodString;
212
219
  username: z.ZodOptional<z.ZodString>;
213
220
  avatarDataUrl: z.ZodOptional<z.ZodString>;
221
+ bio: z.ZodOptional<z.ZodString>;
222
+ accentColor: z.ZodOptional<z.ZodNumber>;
214
223
  }, z.core.$strip>;
215
224
  declare const AclChangeSchema: z.ZodObject<{
216
225
  type: z.ZodLiteral<"acl-change">;
@@ -288,17 +297,24 @@ export declare const CoreMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
288
297
  accentColor: z.ZodOptional<z.ZodNumber>;
289
298
  profileDocId: z.ZodOptional<z.ZodString>;
290
299
  profileUpdatedAt: z.ZodOptional<z.ZodString>;
300
+ isHub: z.ZodOptional<z.ZodBoolean>;
291
301
  }, z.core.$strip>, z.ZodObject<{
292
302
  type: z.ZodLiteral<"friend-request">;
293
303
  v: z.ZodDefault<z.ZodNumber>;
294
304
  fromNodeId: z.ZodString;
295
305
  fromUsername: z.ZodString;
306
+ bio: z.ZodOptional<z.ZodString>;
307
+ avatarDataUrl: z.ZodOptional<z.ZodString>;
308
+ accentColor: z.ZodOptional<z.ZodNumber>;
296
309
  isHub: z.ZodOptional<z.ZodBoolean>;
297
310
  }, z.core.$strip>, z.ZodObject<{
298
311
  type: z.ZodLiteral<"friend-accept">;
299
312
  v: z.ZodDefault<z.ZodNumber>;
300
313
  fromNodeId: z.ZodString;
301
314
  fromUsername: z.ZodString;
315
+ bio: z.ZodOptional<z.ZodString>;
316
+ avatarDataUrl: z.ZodOptional<z.ZodString>;
317
+ accentColor: z.ZodOptional<z.ZodNumber>;
302
318
  isHub: z.ZodOptional<z.ZodBoolean>;
303
319
  }, z.core.$strip>, z.ZodObject<{
304
320
  type: z.ZodLiteral<"friend-accept-ack">;
@@ -393,6 +409,8 @@ export declare const CoreMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
393
409
  nodeId: z.ZodString;
394
410
  username: z.ZodOptional<z.ZodString>;
395
411
  avatarDataUrl: z.ZodOptional<z.ZodString>;
412
+ bio: z.ZodOptional<z.ZodString>;
413
+ accentColor: z.ZodOptional<z.ZodNumber>;
396
414
  }, z.core.$strip>, z.ZodObject<{
397
415
  type: z.ZodLiteral<"acl-change">;
398
416
  v: z.ZodDefault<z.ZodNumber>;
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/protocol/messages.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/protocol/messages.ts"],"names":[],"mappings":"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"}
@@ -87,12 +87,21 @@ const ProfileResponseSchema = z.object({
87
87
  accentColor: z.number().optional(),
88
88
  profileDocId: z.string().optional(),
89
89
  profileUpdatedAt: z.string().optional(),
90
+ isHub: z.boolean().optional(),
90
91
  });
91
92
  const FriendRequestSchema = z.object({
92
93
  type: z.literal("friend-request"),
93
94
  v: wireVersion,
94
95
  fromNodeId: z.string(),
95
96
  fromUsername: z.string(),
97
+ // identity info sent alongside a friend request regardless of the
98
+ // sender's own profile visibility setting - the recipient hasn't
99
+ // agreed to anything yet, but seeing a name/avatar/bio rather than a
100
+ // bare node id is expected for a request the sender is actively
101
+ // initiating themselves.
102
+ bio: z.string().optional(),
103
+ avatarDataUrl: z.string().optional(),
104
+ accentColor: z.number().optional(),
96
105
  isHub: z.boolean().optional(),
97
106
  });
98
107
  const FriendAcceptSchema = z.object({
@@ -100,6 +109,9 @@ const FriendAcceptSchema = z.object({
100
109
  v: wireVersion,
101
110
  fromNodeId: z.string(),
102
111
  fromUsername: z.string(),
112
+ bio: z.string().optional(),
113
+ avatarDataUrl: z.string().optional(),
114
+ accentColor: z.number().optional(),
103
115
  isHub: z.boolean().optional(),
104
116
  });
105
117
  const FriendAcceptAckSchema = z.object({
@@ -171,6 +183,8 @@ const IdentityUpdateSchema = z.object({
171
183
  nodeId: z.string(),
172
184
  username: z.string().optional(),
173
185
  avatarDataUrl: z.string().optional(),
186
+ bio: z.string().optional(),
187
+ accentColor: z.number().optional(),
174
188
  });
175
189
  const AclChangeSchema = z.object({
176
190
  type: z.literal("acl-change"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@freqhole/haruspex",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "freqhole auth domain: identity, webauthn, knock + friendz protocols, permissions",
@@ -59,7 +59,7 @@
59
59
  }
60
60
  },
61
61
  "scripts": {
62
- "build": "tsc -p tsconfig.json",
62
+ "build": "cp ../README.md ./README.md && tsc -p tsconfig.json",
63
63
  "typecheck": "tsc --noEmit",
64
64
  "test": "vitest run"
65
65
  },