1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 | # The ardegazu.ro ecosystem — working notes for AI sessions
You are inside the workspace of **ardegazu.ro**: a suite of serverless p2p
browser apps (chat, whiteboard, six games) plus a hub, all static, all
IPFS/IPNS-hosted, sharing one managed relay+mailbox at `signal.ardegazu.ro`.
There are no servers, no accounts, no databases — rooms are capability URLs,
everything is end-to-end sealed, and every repo is published anonymously.
**Start here:** `dev/` (workspace-relative) is the dev-management suite. Its
`apps.tsv` is the single source of truth for what exists and where. Its
`bin/ardz` CLI encodes the release/publish flow — prefer it over doing the
steps by hand:
```
ardz status | doctor | workspace # orient, verify, bootstrap
ardz dev <name> | relay # dev server / dev relay (:9090)
ardz build|release <names…|all> # build; bump+deploy to IPFS/IPNS
ardz publish-src <names…|all> # anonymity-gated source mirrors
ardz kit-release <kit> # package release + sha-bump consumers
ardz new <name> <host> # scaffold a new p2p game
ardz new-app <name> <host> <live|rooms> # scaffold a p2p app, CLJS (live =
# game stack; rooms = chat stack +
# durable log)
ardz new-bot <name> # scaffold a resident bot
```
## The map
All repos live side by side under the workspace root, named exactly as in
`apps.tsv`:
| name | repo | what |
|---|---|---|
| home | `home/` | the hub: catalog-first multi-view PWA (`catalog.json`-driven) + identity card + `/id/` bridge + friends/presence/invites/leaderboards |
| chat | `chat/` | e2e chat + calls (libp2p v2 + OrbitDB; the original p2p core) |
| board | `board/` | e2e infinite whiteboard (+ invite-only access layer) |
| game1–6 | `game1/`…`game6/` | games (libp2p v3, CLJS; vendored `client/src/<name>/net/` byte-identical except one protocol-prefix line) |
| theme | `theme/` | the shared theme kit (`ardegazu-theme`): tokens/reset/shared components as one CSS file, mirrored at `cdn.ardegazu.ro/theme/v1/theme.css` |
| id-kit | `id-kit/` | the suite identity package: Ed25519 seed, profile, the cross-app iframe bridge |
| social-kit | `social-kit/` | friends, presence, invites, co-signed leaderboards, the paste/invite chips |
| dev | `dev/` | this suite; `git/` is the (non-repo) mirror assembler |
Canonical docs: `game1/docs/NEW-GAME-PROMPT.md` (how games are built),
`dev/docs/NEW-APP-PROMPT.md` (non-game apps, both stacks),
`dev/templates/bot/docs/NEW-BOT-PROMPT.md` (resident bots),
`chat/docs/PROTOCOL.md` (crypto spec), `chat/docs/CHANGELOG.md`,
`dev/docs/CLJS.md` (the ClojureScript migration canon: deps.edn +
shadow-cljs conventions, deterministic dist, gate checklist — the suite is
CLJS; kits/apps/bots follow that doc; JVM ≥ 17 + clojure CLI
needed on the dev machine only, the VPS never builds),
each kit's README.
## House rules (hard-won — do not relearn them)
1. **Anonymity is absolute.** Every repo commits as `<ident> <ident@noreply.local>`
(repo-local git config; `ardz workspace` sets it). Publish gates decompress
every mirror object and abort on identity strings. Newer gates read private
patterns from `~/.config/cod-sursa/idpat` — those also forbid the AI
assistant's name, so: no co-author trailers, no assistant-config dirs
tracked (they're gitignored with a glob-escaped pattern), and prefer
targeted `git add <files>` over `git add -A` in these repos.
2. **Kits are consumed as sha-pinned npm git deps** from `git.ardegazu.ro`
(dumb-HTTP mirrors; loose objects make npm's clone work). npm silently
reuses a stale lockfile resolution when only the committish changes — the
ONLY reliable bump is `npm install <pkg>@git+https://git.ardegazu.ro/<kit>.git#<sha>`.
`ardz kit-release` does all of this.
3. **Deploys**: `ird ipfs add client/dist` → re-pin as `site:<host>` → `ird
ipfs ipns publish <host> <cid>` → unpin the previous `site:<host>` pin only
(never touch `offline:*` or other pins). `ardz release` does this. home,
chat, board, banca and bursa are `versioned=y` — release bumps `client/version.json`
(commit the bump after) or installed PWAs won't see the update banner.
4. **The apex service worker precaches the shell ONLY — `/id/` is strictly
network-only.** `/id/` is the identity bridge every app embeds; a
stale-cached bridge freezes the suite's identity protocol. The workbox
config in `home/client/scripts/build.mjs` excludes it three redundant ways
(`globIgnores: ["id/**"]`, a `NetworkOnly` runtime route on `/\/id(\/|$)/`,
`navigateFallbackDenylist`) — any workbox change must preserve all three,
and the same build gate-asserts all three against the emitted `sw.js`.
`version.json` and `catalog.json` are never precached (globPatterns omit
`.json`); updates arrive via the version.json banner (manual registration
in `home/client/src/home/update.cljs`; `clientsClaim: true`,
`skipWaiting: false`).
5. **node ≥ 22** for the dev relay and engines (`ardz relay` finds it via nvm);
the shell default may be older.
6. **Vendoring convention.** *CLJS line (the only line for games)* —
`game1` is the canon: `net/`, `id/boot.cljs`, `i18n/runtime.cljs` stay
byte-identical across CLJS apps **modulo the namespace rename**
(`game1.` → `<name>.`) plus the one protocol-prefix line in
`net/peers.cljs`. That prefix is **whatever the deployed build already
speaks, not the codename** — valley-blocks' is `/game2/2/`, the sole
exception; guess it and interop dies silently as a negotiation failure.
*Rooms line — NOT vendored any more.* The durable core (`js.cljs` +
`lib/{access,crypto,descriptor,encryption,log,net,orbit-identity,protocol,
turn}`) lives only in `rooms-kit`; chat, board and every new rooms app
sha-pin it and put `node_modules/ardegazu-rooms-kit/src` on `client/deps.edn`'s
`:paths`, requiring it as `ardegazu.rooms.*` — no copy, no rename, one fix
site. Still copied from chat: `lib/mailbox.cljs`, `lib/selftest.cljs` and
`stores.cljs` (`canon.tsv` gates the first two; `i18n/runtime.cljs` is still
game1's).
`lib/protocol.cljs` is each app's own. **No protocol-prefix delta** — the
protocol ids, the OrbitDB provider type and the domain tags stay chat's, and
`APP-SALT` is what separates a fork's rooms.
*TS line — GONE* — board and home ported; no `client/src/net/`,
`id/boot.ts`, `client/src/lib/` or vendored `runtime.ts` survives
anywhere. `game1`'s `i18n/runtime.cljs` is the single canon: fix
once there, replicate. Canon docs: `game1/docs/I18N.md`,
`dev/docs/CLJS.md`.
The scaffolders (`ardz new`, `new-app`, `new-bot`) copy vendored files
from the canon repos at scaffold time (templates hold only the bespoke
skeleton); every scaffold arm — `ardz new`, **both** `new-app` variants
and `new-bot` — is ClojureScript: the TypeScript arms (and the last TS
template, the old bot scaffold) are retired, the suite publishes only
Clojure/ClojureScript.
7. **Dev ports are 4173/5173 only** (the relay's origin allowlist). The
mailbox mint is origin-gated too — test it from a browser, curl gets
"origin not allowed".
8. **Adding an app = one entry in home's `client/catalog.json`** (schema v1:
id/name/host/kind/tagline/description/tags/accent/glyph/status; optional
`lb {g,maxScore}` for leaderboard games, optional `glyphSvg` inline
override) plus the `apps.tsv` row (`ardz new` writes that one). The hub
renders cards, app/game sections and the boards picker from catalog.json
at runtime (bundled snapshot as fallback) — bespoke glyph art goes in
home's `client/src/home/glyphs.cljs`, keyed by the `glyph` field. Localized
tagline/description live in an additive per-entry `i18n: {ro: {...},
hu: {...}}` map — schema stays v1 (old hubs ignore it; never bump `v`
for additive fields). Still manual (known follow-ups): the git-site
index card (`git/index.html`) and social-kit's `SUITE_APPS`.
9. **Committed files never contain local filesystem paths.** The manifest
`dir` column is workspace-relative (bare repo names; `ardz` resolves them
against the dev repo's parent), the assembler lives at `<workspace>/git`,
and the `idpat` gate patterns include path fragments — a leaked path
aborts the publish.
10. **The cdn theme is versioned by directory**: `cdn.ardegazu.ro/theme/v1/theme.css`
tracks `ardegazu-theme`'s major; a breaking token change bumps the major
and lands at `/v2/` so hot-linked pages never shift. In-place tuning of
token values (same names, same feel) stays in `/v1/`.
11. **The Node kits' WebRTC natives never share a process.** `peer-kit`
(libp2p v3 → node-datachannel 0.33) and `rooms-kit` (libp2p v2 →
@ipshipyard/node-datachannel 0.26) each load their own build of
libdatachannel; two copies in one process abort it (ThreadSafeCallback
cancellation). The `bot` runs chat/board rooms in per-room worker
processes — keep that shape in anything that consumes both kits.
## Architecture in one breath
One Ed25519 seed is the suite identity (id-kit), picked up everywhere via a
hidden same-site iframe at `ardegazu.ro/id/` with per-app localStorage
mirrors (offline boot never waits). The social layer (social-kit) rides
gossipsub topics only — pairwise channels derived by static-static DH of
suite X25519 keys, identity-addressed mailbox inboxes for offline, envelopes
signed-then-wrapped and deduped by id across transports. Leaderboards are
match receipts co-signed by ≥2 identity-verified players, dropped into public
per-game weekly mailbox rooms (the TTL is the window) and gossip-merged for
all-time. The hub is a hash-routed multi-view PWA (`#/apps` `#/about` `#/you`
`#/boards` `#/bots` — hash so one build serves the apex and `/ipfs/<cid>/`
alike) that renders its catalog (apps + the resident bots) from
`catalog.json` at runtime. Presence exists only while a tab is open; the hub
is the tab.
|