Commit Graph

7 Commits

Author SHA1 Message Date
type-two
47b51b98ca 🔒 session-token credential binding + admin-guard/CSRF hardening (adversarial review)
Fable flagged that stateless session tokens bound only to uid+expiry — so an
admin action couldn't actually invalidate a live 30-day cookie. Reproduced 3
facets, all one root cause, all fixed by binding the token to the account's
credential state:
- make_token/read_token/_bind: token = uid:exp:bind:sig where
  bind = hmac(secret, 'uid:created:salt')[:16]; read_token re-derives it from the
  user's CURRENT row and rejects on mismatch/missing. So a token dies on account
  DELETE (no ghost session/writes), password RESET (salt rotates → admin can truly
  lock someone out), and SQLite id-REUSE (different created → no identity takeover).
  Old 3-part tokens fail to parse → a one-time re-login. No schema change.

A follow-on adversarial review (4 security lenses × find→refute×2, GO gate) then
surfaced 3 low-severity issues, all fixed here too:
- self-de-admin guard used  (identity) — {admin:0}
  / '' / 'false' / [] slipped past and could strand a sole db-admin. Now only a
  real JSON bool toggles admin (closes the bypass AND the truthy-string mis-grant).
- signup invite claim was check-then-write (double-spend under concurrency) — now
  an atomic  +
  rowcount check; signup/admin-edit wrap the UNIQUE writes in try/except
  IntegrityError → friendly message instead of a 500.
- login-CSRF (Lax cookie only): hub.py _api now blocks cross-site mutating requests
  by Origin (allowlist godstrument.pro/localhost + Host-match fallback so legit
  traffic always passes; safe GETs never blocked).

Verified: auth.py --selftest (delete/reset/id-reuse kill the token; guard bypass
closed for every falsy value); live curl (CSRF 401/401/401/403, GET never blocked);
real-browser flow (new-format cookie authenticates through a page load, admin table
renders, same-origin admin POST passes CSRF). Console clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 09:51:10 +10:00
type-two
b8908504d3 commune v2 — signed-in players, hosted rooms, invitations, host allocation
Hub: identity now comes from the gs_session cookie riding the websocket
handshake (auth._uid_from_cookies -> username per connection; spoof-proof).
On the read-only public hub the commune requires sign-in. Rooms are hosted:
create names the room; invitations go to present, signed-in users by
username; accept/decline; leave any time (host leaving disbands); the host
allocates sections, members claim free ones (hub arbitrates conflicts); and
voice-state is relayed ONLY from the section's holder — enforced server-side.
Roominfo broadcasts keep every member's view of the room identical.

Client: invitation inbox with join/decline in the commune panel, host desk
(invite + allocate rows), identity from the signed-in account, right-click
voice items show holders ("held by X"), presence tag survives reconnects.

Verified full protocol on the live test hub: host -> invite delivered ->
accept -> roominfo both sides -> host allocates bass to peer -> peer's state
applied on host's instrument (1.44x, menu shows holder).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 01:01:23 +10:00
type-two
0a4c28b4c2 the commune (play together via hub relay) + the stage (project to screens)
- hub.py: commune relay — {commune:{room,...}} messages are broadcast verbatim
  to other clients in the same room (allowed even on the read-only public hub;
  peer state never touches hub state). Room tag per ws, cleaned on disconnect.
- viz commune: join a room by word (panel via sky menu), claim voices and the
  godtime from right-click menus or the panel picker; owned sections (mute/
  level/trim, groove steps+on, arranger lane, bpm) diff-sync every 600ms;
  claims/take-overs announced in the ticker; late joiners get re-claims.
  Verified two-way through the live hub: peer state applied (level 1.70x),
  page claims relayed to peers. Bluetooth deliberately not used — a web page
  cannot be a BT peer; the hub is the meeting place, LAN or planet-wide.
- viz stage: window.open + canvas.captureStream(30) mirror window for
  projectors/AirPlay displays; double-click fullscreen; camera modes: whole
  view / follow one node / frame a station+satellites (smoothed glide),
  switchable live from the right-click menus.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 22:39:51 +10:00
type-two
e69b7e2ad6 Accounts, socio-economic feeds, and hub fixes (track deployed work)
Captures backend work already running on godstrument.pro but never committed:
- auth.py: invite-only accounts + per-user presets (SQLite, scrypt, signed
  stateless sessions), mounted by hub.py at /api/*
- hub.py: /api static+API handler, readonly public mode, full route spec in hello
- socio-economic / market / fire / debt / crypto workers + normalize/transform
- .gitignore: never commit godstrument_users.db* or auth_secret
- test_fixes.py: framework-free self-check for the review fixes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 16:18:35 +10:00
60173d44cb Add socio-economic data, performance mode, spells (full-state templates)
- world_bank.py: poverty, food security, fertility, life expectancy (World Bank)
  folded into the "shadow" / "bright" concept groups
- spells: save/load now captures the full live mix (gains/mutes/freezes), not
  just the wiring; TEMPLATES panel renamed SPELLS
- performance mode (press P): clean projection view + rotating "dispatches from
  the world" text readout for live shows

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 02:37:03 +10:00
a039ee7d7c Add dark/yang data, concept groups, named templates, editing console, Strudel kit
- world_debt.py + world_econ.py: US national debt + inflation (the dark half)
- concept groups: "the shadow" / "the bright" — group sources by feeling
- named templates: hub save_patch/load_patch + console TEMPLATES panel
- editing console: runtime add/remove/set route + make_group; drag-to-patch,
  shift-click inspector, cmd-select grouping in the viz
- planetary orbital LFOs per group; almanac + ephemeris workers
- Web MIDI (out + learn) in the console; strudel/godstrument.md starter kit

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 02:25:19 +10:00
8deb65b4fe Godstrument: a multi-modal sensor-fusion instrument
Everything — your hand, the room, a satellite, the markets, the sky — becomes an
OSC control signal fused through a modulation matrix. Includes:
- hub + normalize (One-Euro) + matrix (curves/gates/quantize) + transform (tweaks/groups)
- 20+ workers: sim sensors, 8 keyless world feeds, ephemeris/almanac/clock (computed),
  time-warp replay (quakes/weather/db), and the dealgod market warehouse feed
- planetary orbital LFOs, SQLite recorder, city targeting
- live browser console: mute, group macros, drag-to-patch, inspector, Web MIDI

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 02:13:05 +10:00