8.3 KiB
bincio_wiki — deployment plan
Architecture overview
Three domains, one shared user database:
bincio.org — auth hub: login, registration, links to the two apps
activity.bincio.org — bincio_activity (moved from bincio.org)
wiki.bincio.org — bincio_wiki (new)
Shared DB: /var/bincio/data/instance.db
↑ used by all three, lives with bincio_activity's data
Login happens at bincio.org. The session cookie is set with domain=.bincio.org
so it is automatically valid on activity.bincio.org and wiki.bincio.org. No
per-app login page needed. Each app's FastAPI validates the shared session token.
After login, the bincio.org home page shows the apps the user has access to
(based on their access flags). If not authenticated, the landing page IS the
login form.
User model
One unified users table with two access flags:
| flag | meaning | cap |
|---|---|---|
wiki_access |
can log in to wiki.bincio.org | 100 |
activity_access |
can log in to activity.bincio.org | 30 |
A user can have one or both. Registration is always for wiki first; activity access is granted separately (invite flag or admin toggle). The caps are independent: 100 wiki users total, 30 activity users total.
All existing bincio_activity users get wiki_access=1, activity_access=1.
New wiki-only users get wiki_access=1, activity_access=0.
Schema changes (bincio_activity DB)
New columns on users
ALTER TABLE users ADD COLUMN wiki_access INTEGER NOT NULL DEFAULT 1;
ALTER TABLE users ADD COLUMN activity_access INTEGER NOT NULL DEFAULT 0;
Migration for existing users:
UPDATE users SET wiki_access = 1, activity_access = 1;
New column on invites
ALTER TABLE invites ADD COLUMN grants_activity INTEGER NOT NULL DEFAULT 0;
The invite creator chooses whether the invite grants activity access, subject to this rule: you can only grant access you yourself have.
| Inviter type | Can create wiki invite | Can set grants_activity=1 |
|---|---|---|
| Wiki-only member | Yes (up to 3) | No |
| Activity member | Yes (up to 3) | Yes — their choice |
| Admin | Yes, unlimited | Yes |
The API enforces this: POST /api/invites returns 403 if the caller tries to
set grants_activity=1 without having activity_access=1 themselves. The UI
hides the toggle entirely for wiki-only users.
Caps are enforced at registration time regardless of who issued the invite: if the wiki is at 100 users or activity is at 30 users, registration fails even with a valid unused code.
Settings table
INSERT OR REPLACE INTO settings VALUES ('max_wiki_users', '100');
INSERT OR REPLACE INTO settings VALUES ('max_activity_users', '30');
-- remove or ignore the old generic 'max_users' key
What needs to be built
1. bincio.org — auth hub (changes to bincio_activity)
FastAPI (bincio_activity)
POST /api/auth/login: after bcrypt check, also verify the user's access flag for the app they're logging in from (sent asappparameter, or inferred fromReferer). Actually: login at bincio.org grants a general session; the flag check happens at/api/meon each subdomain.GET /api/me: addwiki_accessandactivity_accessto the response.POST /api/invites: accepts optionalgrants_activity: boolfield.- Session cookie: change
domainfrom unset (host-only) to.bincio.orgso it propagates to subdomains. This is the key change. - Cap logic: registration checks
max_wiki_users(total users withwiki_access=1) and optionallymax_activity_usersif the invite hasgrants_activity=1.
Astro (bincio.org landing page)
- The landing page (
/) becomes: login form if not authenticated, app selector if authenticated. - App selector shows links to
activity.bincio.organdwiki.bincio.orgbased on the user's access flags returned by/api/me. - Invite management moves here from bincio_activity. The
/invites/page stays atbincio.org(not at either subdomain) so admins can issue both wiki-only and wiki+activity invites from one place. The invite creation form gets a toggle: "wiki only" (default) vs "wiki + activity". - Invite links always point to
bincio.org/register/?code=XXXXXXXX. After registration the user getswiki_access=1always, andactivity_access=1only if the invite hadgrants_activity=1. - The existing
/register/,/reset-password/pages stay at bincio.org. - Remove the activity app content from bincio.org (it moves to the subdomain).
bincio_activity moves to activity.bincio.org
- nginx: add
activity.bincio.orgserver block (same webroot and proxy as currentbincio.orgblock). - bincio.org nginx: strip activity routes (
/u/,/activity/,/data/) and serve only the auth hub static files + proxy/api/to port 4041. - All internal links in bincio_activity site that are root-relative (
/u/dave,/activity/123) stay as-is since the app now owns its own domain.
2. bincio_wiki auth (edit/server.py)
- Shared DB: connect to
/var/bincio/data/instance.db(configurable viaSHARED_DB_PATHenv var, defaults to../bincio_activity/data/instance.dblocally). GET /api/me: validate session token frombincio_sessioncookie, checkwiki_access=1, return{handle, display_name, is_admin}or 401.POST /api/auth/logout: delete session from shared DB.- No
/api/auth/loginin wiki: login happens atbincio.org. - All CRUD endpoints (
/pages,/stories) require a valid session withwiki_access=1.
3. bincio_wiki auth wall (Astro)
Base.astro: addfetch('/api/me')on load → on 401, redirect tohttps://bincio.org/login/?next=https://wiki.bincio.org(or just bincio.org with no next param, since the app selector handles it).- No login page in bincio_wiki — login is centralised at bincio.org.
- The
?next=redirect is optional / nice-to-have for first iteration.
Phase plan
Phase 0 — Schema migration (local + VPS)
- Add
wiki_access,activity_accessto users; addgrants_activityto invites. - Update settings:
max_wiki_users=100,max_activity_users=30. - Migration script:
deploy/migrate.sql.
Phase 1 — bincio_activity auth changes
- Cookie domain →
.bincio.org. /api/meresponse: include access flags.- Login: no flag check (session is general), flag check is per-app at
/api/me. - Registration: enforce
max_wiki_users(wiki_access count). If invite hasgrants_activity=1, also enforcemax_activity_users. - Invite creation: add
grants_activityfield. - On registration: set
wiki_access=1always,activity_access=invite.grants_activity.
Phase 2 — bincio_wiki FastAPI auth
- Connect to shared DB.
- Implement
GET /api/mewithwiki_accesscheck. - Implement
POST /api/auth/logout. - Add
require_session()dependency to all CRUD endpoints.
Phase 3 — Astro auth wall (bincio_wiki)
Base.astro:/api/mecheck → redirect tobincio.orgon 401.- No login page in wiki.
Phase 4 — bincio.org landing page
- Update home page: login form (unauthenticated) / app selector (authenticated).
- Invite form: add activity toggle.
- Keep existing register/reset-password pages.
Phase 5 — nginx migration
- Add
activity.bincio.orgserver block (certbot for the new subdomain). - Update
bincio.orgblock: serve only auth hub, strip activity routes. - Add
wiki.bincio.orgserver block.
Phase 6 — Deploy & verify
- Push both apps to VPS.
- Run migration SQL on the live DB.
- Restart services.
- Smoke test: login at bincio.org, verify cookie reaches both subdomains.
Notes
- Local dev: both apps set
SESSION_DOMAINenv var; if unset, cookie is host-only (fine for localhost). In production always set.bincio.org. - bincio_activity data dir: stays at
/var/bincio/data/. The wiki just opens the DB there; it doesn't own it. - Wiki content: lives at
/var/bincio/wiki/(pages and stories markdown). - Admin tools:
is_admin=1users can toggle access flags on other users via an admin endpoint. First iteration: do it directly in sqlite on the VPS if needed.