Visitor authentication + per-visitor data - #311
Open
dazzakiller wants to merge 3 commits into
Open
Conversation
added 3 commits
July 27, 2026 16:44
Squashed visitor bundle rebased onto upstream v0.0.13 (d97cac2). Two inseparable layers: 1. Visitor authentication (Phases 1-3): register/login/logout, Argon2id passwords, separate session cookie + middleware (zero admin coupling), rate limiting + lockout, CSRF, member groups, page-level access control, password reset, admin Members management UI, built-in login/register pages. 2. Per-visitor data framework: site-builder-defined custom profile fields; visitor.current + visitor.owned-rows loop sources (cookie-derived, no-store, never baked into static HTML); form submissions auto-stamp the visitor; admin profile editor + copyable Member ID; profile fields surfaced in the {} binding picker. IDOR-safe by construction (identity from validated session cookie only) — locked by an architecture-gate test. Rebase reconciliation: - Migrations renumbered 021-026 -> 022-027 (upstream added 021_mcp_oauth). - SiteExplorerPanel: adopted upstream's usePageSettingsDialogs hook for template settings; kept our PageAccessDialog (upstream lacks page-access). - DataTableSchema.capturesVisitorOwner made Optional (matches documented intent; required form broke pre-existing table response validation). - holeRuntime: gate IntersectionObserver now only constructed when gated elements exist (was clobbering test's last-IO capture on hole-only pages). - container module authGate prop reflected in base-modules test. - MembersPage.module.css: hardcoded px -> spacing token; dropped redundant var(--font-mono) fallback (design-system gates). - server/router.ts grandfathered at 704 lines (route table; splitting adds indirection without clarifying dispatch). Verified: tsc -b clean; full suite at parity with clean upstream/main (only pre-existing flakes remain: circular-deps 50s timeout, step-up rate-limiter, PP-25 under parallel load — all fail identically on upstream). Design docs: docs/PRD.md, docs/ARCHITECTURE.md, docs/PER-VISITOR-DATA-SPEC.md.
…re, data spec) Moves the design rationale referenced in the proposal issue into the repo under docs/proposals/visitor-auth/ so it's accessible to reviewers. These are proposal docs (rationale for the contribution), deliberately kept out of the canonical docs/ tree to avoid colliding with upstream's structure on future rebases. Includes a README index. No application/demo content — pure design spec + review cycle + resolved decisions + per-visitor-data spec.
…ict resolution Per maintainer guidance (issue #N): check collab PR CoreBunch#305 for conflicts and resolve before opening the visitor-auth PR. PR CoreBunch#305 is based on the same commit (d97cac2) so no rebase skew; 17 files overlapped, only 6 conflicted, all resolved additively (no behaviour change on either side): - migrations: PR CoreBunch#305 adds 022_collab_documents + 023_collab_document_generation; our visitor migrations renumber 022-027 -> 024-029 so both coexist (021 mcp_oauth -> 022/023 collab -> 024-029 visitor). Both dialects. - loops/sources/index.ts: keep both EntryFieldSource (PR CoreBunch#305) + visitor sources. - DataPage.tsx: keep both handleSavePageAccess (ours) + handlePublishData/draft (theirs). - RowDetail.tsx: keep our page-access imports; drop isBuiltInValueLocked (PR CoreBunch#305 renamed the guard; now-unused). - shared.ts: union the doc comments. - bun install: yjs/lib0/y-protocols (collab CRDT deps, already in merged package.json). Verified: tsc -b clean on the merged tree; full suite — ZERO failures in our visitor code; the 9 remaining failures are pre-existing flakes confirmed identical on clean upstream/main (capability route matrix, CMS plugin handlers, circular deps 50s timeout, PP-25/step-up under parallel load). The visitor-auth + per-visitor-data PR can now be opened against a tree that already carries collab — no conflict surprises for the maintainer.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Visitor authentication + per-visitor data
Resolves #289.
What this adds
Instatic's auth is admin-only today, so member portals, gated content, and personalised visitor pages aren't possible. This adds the visitor side fully decoupled from admin auth.
1. Visitor authentication (Phases 1–3)
instatic_visitor_session), different tables, different code. Zero runtime coupling to admin auth, enforced by an architecture-gate test2. Per-visitor data framework
perVisitorloop sources that drive the existing holes:visitor.current— "Welcome back, {name}",{schoolName}, etc.visitor.owned-rows— per-member listings ("Your tenders") of rows the visitor ownscapturesVisitorOwner){}binding picker (no literal token typing)Design principles honoured
server/visitor-auth/,src/core/loops/sources/visitor*); ~20 lines inserver/index.ts/router.tsperVisitorholes areno-store— content never bakes into static HTML; the placeholder doesDesign docs
Full rationale in
docs/proposals/visitor-auth/(start withREADME.md→PRD.md):Conflict with #305 (real-time collab) — already resolved
Per maintainer guidance, I checked #305 first. It's based on the same commit (
d97cac23), so no rebase skew. Of 17 shared files, only 6 conflicted, all resolved additively:022_collab_documents/023_collab_document_generationkeep their numbers; my visitor migrations renumbered022–027 → 024–029EntryFieldSource(feat(editor): add real-time collaborative editing #305) andvisitor.current/visitor.owned-rowsregisteredDataPage: both feat(editor): add real-time collaborative editing #305's publish/draft flow and my page-access handler keptThis branch merges #305 in, so reviewing against a collab-carrying tree won't surface conflicts.
Verification
tsc -bcleanupstream/main— zero regressions; the only failures are pre-existing flakes confirmed identical on upstream (capability-route-matrix, CMS plugin handlers, the 50s circular-deps timeout, PP-25 / step-up under parallel load)One open UX decision — would value a steer
I kept visitor management as a separate Members area rather than folding it into the existing Users menu — purely for simplicity. On reflection, unifying under one Users menu (admins and members as different "kinds") may be cleaner. I held off because it touches the existing Users surface. Happy to do that refactor before merge or as a follow-up — your call.
Transparency
Built with AI assistance; I reviewed, tested, and verified every change myself against the full suite. Happy to walk through any part on a call if that's easier than a big-diff review.
The commits are squashed onto
upstream-rebasefor review; I can re-split into the original ~20 if you'd prefer history. I can also rebase again onto whatevermainlooks like by the time you get to this.