coulomb-social/workplans/CSOC-WP-0004-app-shell-and-space-content.md
tegwick edfdd79208 Finish CSOC-WP-0003 and CSOC-WP-0004; residual intakes for Case B
Close self-registration workplan with Case A proven and Create account
entry implemented; park public registration enablement and identity
negatives as CSOC-IN-0001/0002. Complete app-shell workplan with T06
operator runbook (seed, bind, webhook, smoke) and smoke doc updates.
2026-08-12 10:59:25 +02:00

258 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: CSOC-WP-0004
type: workplan
title: "App shell entry and Forgejo-backed space content"
domain: communication
repo: coulomb-social
status: finished
owner: bernd
topic_slug: coulomb-social
created: "2026-08-10"
updated: "2026-08-12"
# note: T07 added same day — principal diagnostics via profile menu
depends_on:
- CSOC-WP-0002
related:
- CSOC-WP-0001
- CSOC-WP-0003
origin: operator
origin_ref: session-2026-08-10-parallel-host-product-path
state_hub_workstream_id: "d10427aa-02d9-4ec9-a466-d7cdb1a9167e"
---
# CSOC-WP-0004 — App shell entry and Forgejo-backed space content
## Context
Identity is live on **`https://app.coulomb.social`**. After Sign in, members
land on an identity **confirmation shell** (“Signed in” + principal dump) with
no product surface. Bubble on apex remains the full product until we choose
cutover.
**Goal for this phase:** build the new implementation toward product usefulness
**before** bulk Bubble data migration. Immediate product foundation:
1. Leave the login confirmation shell into a real **app home**.
2. Establish **space** persistence whose **content is markdown**, stored and
versioned in close connection with **Forgejo** repositories.
Migration of all Bubble spaces is **explicitly later** (`CSOC-WP-0001`).
**Finished 2026-08-12:** T01T07 complete. Operator runbook and smoke pointers
in `docs/deploy.md` and `docs/identity/smoke.md`.
## Out of scope (this plan)
- Apex DNS cutover / Bubble retirement
- Full Bubble inventory or bulk import
- Public self-registration (CSOC-WP-0003 residuals / NetKingdom)
- Full UI parity (Research, marketplace matching, …) beyond space content MVP
---
## T01 — Post-login product entry (leave confirmation shell)
```task
id: CSOC-WP-0004-T01
status: done
priority: high
state_hub_task_id: "7cce67c0-6234-4ef4-ad67-de952f5f4519"
```
Replace the dead-end “Signed in / Principal” page as the primary post-login
destination with an **app home** that a member can use:
- Clear primary navigation: Spaces (and placeholders for later surfaces).
- Compact account control (display name / avatar) opening a **profile menu**
(full principal diagnostics live under **T07**, not on the home body).
- Empty state when the member has no spaces yet (“Create space” or “No spaces”).
- `LOGIN_REDIRECT_URL` and templates updated; design-extract tokens only as needed.
**Done when:** after OIDC login on app.coulomb.social, tegwick lands on app home
(not a debug-only principal card) and can navigate without guessing URLs.
2026-08-11: App home is Spaces empty state; header nav + profile menu; principal
dump removed from home body. Deploy with next image for app.coulomb.social.
## T02 — Space domain model (metadata, tenant-keyed)
```task
id: CSOC-WP-0004-T02
status: done
priority: high
state_hub_task_id: "5fd91718-151d-4216-acf2-2104a45cddf9"
```
Introduce `Space` (name pending Bubble vocabulary alignment) as application
metadata in the app DB:
- `tenant_id`, stable slug, display title, owner/membership linkage to Member
- **no** long-form page bodies in Postgres as the system of record
- optional pointer fields for content binding (repo, default branch, root path)
Migrations + admin + minimal list/detail routes behind auth.
**Done when:** authenticated user can list zero-or-more spaces from DB; tests cover
tenant isolation basics.
2026-08-12: `spaces` app — `Space` + `SpaceMembership`, tenant-scoped list on
`/app/`, detail `/app/spaces/<slug>/`, admin seed path. Tests cover isolation.
## T03 — Content model ADR: markdown + Forgejo
```task
id: CSOC-WP-0004-T03
status: done
priority: high
state_hub_task_id: "628243e0-732f-42c1-b4e3-9b8cd82ea530"
```
Write `docs/adr/ADR-0002-space-content-forgejo-markdown.md` deciding:
- Markdown (and assets) as the **canonical content form** for space pages
- Forgejo repo layout (one repo per space vs monorepo paths; branch policy)
- How the app **reads** content (clone/cache, raw API, webhook invalidation)
- How the app **writes** (direct git push as service account vs user OAuth to Forgejo)
- Relationship to Bubble page/chunk model for later CSOC-WP-0001 mapping
- Secrets: Forgejo tokens via OpenBao / env secret names only
**Done when:** ADR accepted (or explicitly provisional with open questions listed)
and linked from INTENT/SCOPE.
2026-08-12: Provisional ADR-0002 committed; linked from INTENT/SCOPE. One repo
per space, `pages/` root, Forgejo API read for T04; write-in-Forgejo for T05.
## T04 — Read path: render space markdown from bound repo
```task
id: CSOC-WP-0004-T04
status: done
priority: high
state_hub_task_id: "77fa3454-6f2e-4a76-8a0c-ff7e13ca4b6a"
```
Implement a vertical slice:
- Operator or seed binds one space to a Forgejo repo path
- App fetches/renders a markdown page (e.g. `README.md` or `pages/index.md`)
- Authz: member of tenant/space only (flex-auth or coarse membership check)
- Fail closed on missing binding or fetch errors
**Done when:** tegwick can open a space on app.coulomb.social and see rendered
markdown sourced from Forgejo (not Bubble).
2026-08-12: Forgejo raw fetch + bleach-sanitized markdown render; demo fixture
at `docs/space-fixtures/demo/pages/index.md`; `seed_demo_space` management
command; env `FORGEJO_BASE_URL` / optional `FORGEJO_TOKEN`.
## T05 — Write / sync path (minimal)
```task
id: CSOC-WP-0004-T05
status: done
priority: medium
state_hub_task_id: "30ed5def-2718-4379-834c-920e751e4d0b"
```
Minimal authoring or sync so content is not read-only forever:
- either in-app edit → commit to Forgejo, or
- documented “edit in Forgejo / pull request” workflow + refresh webhook
Prefer the smaller path that keeps git as source of truth.
**Done when:** a content change in Forgejo appears in the app without redeploy,
and (if in-app write exists) a save produces a commit without secrets in git.
2026-08-12: **Edit in Forgejo** + **View source** + **Refresh content** on space
detail; repo-scoped cache invalidate; optional push webhook
`POST /app/spaces/hooks/forgejo/` (HMAC or shared secret). Docs:
`docs/spaces-content.md`. No in-app editor (git remains SoR).
## T06 — Seed and runbook for app.coulomb.social
```task
id: CSOC-WP-0004-T06
status: done
priority: medium
state_hub_task_id: "40a880d0-62b9-4ae4-ab3e-074e8901462a"
```
Document operator steps: create Forgejo org/repo, bind space, credentials env
names, smoke checklist on app.coulomb.social. Update `docs/deploy.md` and
`docs/identity/smoke.md` pointers as needed.
2026-08-12: Full operator runbook in `docs/deploy.md` (demo seed, dedicated
repo, webhook, env table, smoke table). Product smoke section in
`docs/identity/smoke.md`. FORGEJO_* names in `.env.example` and `docs/dev.md`.
Content detail remains `docs/spaces-content.md`.
## T07 — Principal diagnostics via user profile menu
```task
id: CSOC-WP-0004-T07
status: done
priority: high
state_hub_task_id: "8487443a-dfd2-4220-a90b-bca2b5b04c4c"
```
Keep the current principal card fields available as **detail information**
reachable from the **user profile menu** in the app chrome (not as the primary
post-login page body). Purpose: refine and diagnose identity wiring during
ongoing user, group, role, and tenant management work.
Include at least the present shell fields (and extend as claims become available):
| Area | Examples |
|------|----------|
| Identity | display name, username, issuer, subject |
| Platform user | user-engine id, user-engine source |
| Tenancy | tenant id / claims |
| Roles & groups | OIDC/groups/roles claims when present |
| Authz | flex-auth / shell decision reason + decision id |
| Session | assurance / AAL hints when present |
UX:
- Profile menu entry e.g. **Account** / **Session details** / **Identity**
- Detail view at a stable path (e.g. `/account/` or `/account/session/`)
- Readable for operators; no secrets (tokens, proxy secrets) ever rendered
- Sign out remains on the menu
**Done when:** after T01 app chrome exists, tegwick can open the profile menu →
principal/session detail page and see the same diagnostic surface formerly on
the signed-in card, without that card being the home page.
Ship with or immediately after **T01** (same PR is fine).
2026-08-11: `/account/session/` holds principal diagnostics (identity, UE,
tenant, roles/groups, assurance, authz). Profile menu → **Session details**.
Session stashes groups/roles/assurance at login (no secrets).
---
## Sequencing
```text
T01 app home entry ──┬─► T07 profile menu principal diagnostics
└─► T02 Space metadata
└─► T03 content ADR
└─► T04 read path (MVP value)
├─► T05 write/sync
└─► T06 runbook
```
## Acceptance (workplan)
1. Post-login journey is product-shaped (app home + spaces), not identity-debug-only.
2. Principal/session diagnostics remain available from the user profile menu (T07).
3. Spaces exist as tenant-keyed app records.
4. Space page content is markdown backed by Forgejo with a working read path.
5. Bubble migration is still not required for demos on app.coulomb.social.
6. CSOC-WP-0001 can map Bubble pages onto the ADR layout when migration starts.
7. Operator runbook documents seed, bind, secrets (names), and smoke (T06).
## Related
- Live host: `docs/deploy.md` (app.coulomb.social parallel to Bubble)
- Identity: CSOC-WP-0002 (done), CSOC-WP-0003 residuals for public registration
- Migration later: CSOC-WP-0001
- Design tokens: `docs/design-extract/`