template 0.8.0: anon, user, admin — three tiers decided in Forgejo, carried by the edge; the door, hardened #21
No reviewers
Labels
No labels
agent-work
agent-working
ultracode
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
open-platform/app-template!21
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "roles-catalyst"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why: gretchy.store went public and every question — who may sign in, who runs the Studio, what a stranger can see — became a hand-rolled iteration (a login list in env, a door pointed at a bridge that does not exist in platform mode). This makes the answers preconfigured for every app born from now on, without boxing an app in.
Three tiers, decided at the auth layer (
src/contracts/viewer.ts,wiki/Roles-and-Access.md):public: truein the org ground (share cards) or in local dev.X-Plat-Perm: admin: org owners on every org repo, repo admins on theirs).PLAT_ADMIN_TEAMS=<team>,<team>grants the same standing to an org team viaX-Plat-Teams— group associations, managed in Forgejo, no login list in app code.manage(write+) stays as the contributor capability.Guards:
requireUser/requireAdmin/requireManage/requireTeam("name")atpreValidation./api/mecarriesrole;/api/adminis the example. SPA:isAdmin(),roleOf(), the tier in the badge.The door (
src/security.ts, first in the lifecycle): every/api,/openapiand flag-registry request answers an anonymous caller 401 with one sentence — before the body parser, validator, content-type gate or 404 handler can say more.PUBLIC_READSis the explicit, reviewed list of anonymous reads (empty by default).src/anon-surface.test.tsbuilds the real app and walks every route as a stranger; anything open and not written down fails the build. Headers + CSP (hash-pinned inline scripts;CSP_EXTRA_SOURCESfor a tile/media host), same-origin JSON-only mutations (403 audited / 415), anonymous rate limit (ANON_RATE_LIMIT).Sign-in on a public app: the edge's
/_plat/login//_plat/logouton this host (plat-auth 0.45.2) from the door in both modes; sign-out in platform mode too. Closes #20.Structure:
src/server.tsis the entry;src/app.tsbuilds the app so tests can inject.contract-emit's main guard matchedcontract-emit.test.jsundernode --testand booted a server from the test — exact-name guard; its fetch presents an edge identity (docs are signed-in only). CI smoke asserts the door semantics.57/57 tests, lint + typecheck clean, contract regenerated. Smoke on the built server: anon 401 on everything private (incl. unknown
/apipaths), reader 200/403/404, owner admin, team-member admin withPLAT_ADMIN_TEAMS, cross-site POST 403, form POST 415.🔴 CI run
checkfailed on78995ff876— queuing an agent to look (addedagent-work).🔎 Preview is live for QA: https://pr-21-app-template-plat.open-platform.sh