Adopt stage-1 capability cut and product capability model

Persist capability/feature vocabulary, v0 model, and founder stage-1 must set
(onboarding, spaces/pages with Title/Abstract/Visual, page copy and transfer).
Mark CSOC-WP-0001-T03 done; add CSOC-WP-0006 for implementation.
This commit is contained in:
tegwick 2026-08-12 13:09:09 +02:00
parent 2dfb5a0bf2
commit bc78cd27fc
13 changed files with 622 additions and 11 deletions

13
docs/capability/README.md Normal file
View file

@ -0,0 +1,13 @@
# Capability and feature model — coulomb-social
Product utility and implementation hierarchy for the Bubble exit and rebuild.
**Local first**; extract durable patterns to HelixForge / reuse-surface later.
| Doc | Role |
|-----|------|
| [`vocabulary.md`](vocabulary.md) | Capability vs feature vs toggle rules |
| [`model-v0.yaml`](model-v0.yaml) | Machine-readable capability map |
| [`stage-1-cutover.md`](stage-1-cutover.md) | First productive-transfer stage (must set) |
| [`../decisions/2026-08-12-feature-cut-stage-1.md`](../decisions/2026-08-12-feature-cut-stage-1.md) | Recorded cut decision |
Related: Bubble inventory, ADR-0002, CSOC-WP-0001-T03.

View file

@ -0,0 +1,194 @@
# coulomb-social product capability model v0
# Vocabulary: docs/capability/vocabulary.md
# Stage-1 narrative: docs/capability/stage-1-cutover.md
schema_version: "0.1"
product: coulomb-social
resource_id: "resource:tenant:coulomb:coulomb-social"
updated: "2026-08-12"
stance: |
Partial rebuild is intentional. Stage 1 enables user transfer and retires
Bubble as productive system; Bubble may remain reference-only. Later stages
add use cases on the rebuild.
stages:
stage_1:
id: stage_1_productive_transfer
title: "Productive transfer / Bubble reference-only"
goal: >
Members use app.coulomb.social for onboarding and space/page work with
Title, Abstract, Visual; page copy and transfer. Apex productive use leaves Bubble.
decision_ref: docs/decisions/2026-08-12-feature-cut-stage-1.md
capabilities:
- id: cap.member-onboarding
title: User onboarding
utility: >
A person becomes and remains a signed-in member of the rebuild without
Bubble for day-to-day authentication.
priority: must_stage_1
depends_on_platform:
- netkingdom-oidc
- user-engine
features:
- id: feat.oidc-sign-in
title: OIDC sign-in (existing users)
status: shipped
- id: feat.jit-member
title: First-login JIT Member + user-engine link
status: shipped
- id: feat.session-diagnostics
title: Session / principal diagnostics
status: shipped
- id: feat.public-registration
title: Public Create account + verified mail
status: blocked
blocked_on: "NK-WP-0025 / CSOC-IN-0001"
toggle: NETKINGDOM_REGISTRATION_URL
- id: feat.post-login-app-home
title: Post-login app home (Spaces)
status: shipped
- id: feat.member-transfer-assist
title: Assisted transfer of Bubble members (no password import)
status: todo
- id: cap.space-content
title: Spaces with markdown content
utility: >
Members organize work in spaces and maintain page content as markdown,
with first-class Title, Abstract, and Visual metadata and CRUD.
priority: must_stage_1
depends_on_platform:
- forgejo
- apps-pg
related:
- docs/adr/ADR-0002-space-content-forgejo-markdown.md
features:
- id: feat.space-list
title: List spaces (tenant-scoped)
status: shipped
- id: feat.space-md-render
title: Render space page from Forgejo markdown
status: shipped
- id: feat.space-edit-forgejo
title: Edit body in Forgejo + refresh/webhook
status: shipped
- id: feat.space-crud
title: Space create / read / update / delete-or-archive (member UI)
status: partial
notes: "Model + admin/seed; member-facing CRUD todo"
- id: feat.space-title
title: Space Title field
status: partial
notes: "DB title exists; member edit UI todo"
- id: feat.space-abstract
title: Space Abstract field
status: partial
notes: "Maps to Space.description until product rename"
- id: feat.space-visual
title: Space Visual (cover/image)
status: todo
- id: feat.page-list
title: List pages in a space
status: partial
- id: feat.page-crud
title: Page create / update / delete (product path)
status: partial
notes: "Git/Forgejo only today; product path todo"
- id: feat.page-title
title: Page Title (structured)
status: partial
notes: "Inferred from H1/filename; frontmatter/UI todo"
- id: feat.page-abstract
title: Page Abstract
status: todo
- id: feat.page-visual
title: Page Visual
status: todo
- id: feat.content-fail-closed
title: Fail closed on missing binding/fetch
status: shipped
- id: cap.page-transfer
title: Transfer page to another space
utility: >
A page (and agreed assets) can be moved from one space to another with
correct membership checks and stable identity after the move.
priority: must_stage_1
features:
- id: feat.page-move
title: Move page between spaces
status: todo
- id: feat.page-move-authz
title: Authz for source and destination spaces
status: todo
- id: cap.page-copy
title: Generate copy of page
utility: >
A member can create an independent copy of a page (optionally into
another space) without manual git-only workflow as the sole path.
priority: must_stage_1
features:
- id: feat.page-duplicate
title: Duplicate page (new slug/title)
status: todo
- id: feat.page-duplicate-assets
title: Copy or re-link page assets
status: todo
# --- later stage (not transfer blockers) ---
- id: cap.social-engagement
title: Social engagement (favorites, follows)
utility: Members favorite and follow people or content.
priority: later
features:
- id: feat.favorites
title: Favorites
status: later
- id: cap.marketplace
title: Marketplace matching
utility: Challenges, methods, and solutions discovery/matching.
priority: later
features:
- id: feat.challenges-methods-solutions
title: Challenge / method / solution surfaces
status: later
- id: cap.monetization
title: Monetize curiosity / payments
utility: Paid offerings or monetization flows.
priority: later
features:
- id: feat.payments
title: Payments integration
status: later
- id: cap.realtime-collab
title: Real-time collaborative editing
utility: Multiple members edit the same page concurrently in-app.
priority: later
features:
- id: feat.collab-editor
title: Collaborative in-app editor
status: later
- id: cap.bubble-workflow-parity
title: Bubble workflow automation parity
utility: Like-for-like Bubble backend workflows.
priority: out
notes: >
Rebuild workflows in code only when product need returns; not a parity goal.
platform_dependencies:
- id: netkingdom-oidc
title: NetKingdom OIDC (KeyCape / Authelia)
- id: user-engine
title: user-engine identity link
- id: forgejo
title: Forgejo git hosting for space content
- id: apps-pg
title: Shared application PostgreSQL
- id: railiance-runtime
title: Railiance deploy of coulomb-social

View file

@ -0,0 +1,126 @@
# Stage 1 cutover — productive transfer set
| Field | Value |
|-------|--------|
| Decision | [`../decisions/2026-08-12-feature-cut-stage-1.md`](../decisions/2026-08-12-feature-cut-stage-1.md) |
| Model | [`model-v0.yaml`](model-v0.yaml) |
| Date | 2026-08-12 |
| Stance | **Partial rebuild is enough** for transfer; extend with later use cases after Bubble is reference-only |
## Goal of stage 1
Move members to **`app.coulomb.social`** as the **productive** home and retire
Bubble on apex as a **productive** system. After transfer:
- Bubble may remain online only as an **implementation reference** (read-only /
archival / comparison), not as the place where new work happens.
- Additional capabilities (marketplace, social graph, monetization, …) ship
**later** on the rebuild without blocking transfer.
## Must capabilities (stage 1)
### 1. User onboarding — `cap.member-onboarding`
Members can obtain and use an account on the rebuild without depending on
Bubble for day-to-day login.
| Feature | Status | Notes |
|---------|--------|--------|
| OIDC sign-in (existing LLDAP/KeyCape users) | shipped | Case A proven |
| JIT Member + user-engine link | shipped | |
| Session / account diagnostics | shipped | `/account/session/` |
| Public Create account + verified mail | partial / blocked | App entry ready; NK mailbox (`CSOC-IN-0001`) |
| Guided first landing on app home | shipped | post-login → Spaces |
| Bulk / assisted member transfer from Bubble | todo | Process + optional import; no password migration |
**Stage-1 acceptance:** known operators and community members can sign in;
new members can register once NK path is live **or** operator-provisioned
LLDAP accounts cover the transfer cohort. No Bubble password import.
### 2. Spaces with markdown content — `cap.space-content`
Members work in **spaces** whose durable content is **markdown** (ADR-0002).
| Feature | Status | Notes |
|---------|--------|--------|
| Space list (tenant-scoped) | shipped | |
| Space detail + render page from Forgejo | shipped | |
| Edit in Forgejo + refresh / webhook | shipped | git SoR |
| **Space CRUD** (create/read/update/delete or archive) | partial | Admin/seed today; **member UI CRUD todo** |
| **Title** on space | partial | Model field exists; member edit UI todo |
| **Abstract** on space | partial | Use `description` as abstract until renamed |
| **Visual** on space (cover/image) | todo | Not in model yet |
| Page list within space | partial | path-based pages; richer list todo |
| **Page CRUD** (create/update/delete markdown pages) | partial | Via Forgejo only; in-app or first-class API todo |
| **Title** on page | partial | From H1 / filename; structured frontmatter todo |
| **Abstract** on page | todo | Frontmatter or metadata |
| **Visual** on page | todo | Frontmatter image / assets |
| Fail-closed missing binding | shipped | |
**Stage-1 acceptance:** members can create and maintain spaces and pages with
**Title, Abstract, Visual** as first-class fields (not only raw git for metadata),
content body in markdown, readable on app host. Exact UX (in-app editor vs
structured form + Forgejo body) can vary; **utility** must not require Bubble.
### 3. Move page between spaces — `cap.page-transfer`
| Feature | Status | Notes |
|---------|--------|--------|
| Transfer page to another space | todo | Move markdown (+ assets) + rewrite links; metadata follows |
| Authz (source + destination membership) | todo | |
**Stage-1 acceptance:** a page can leave space A and appear in space B without
Bubble, with clear ownership after the move.
### 4. Duplicate page — `cap.page-copy`
| Feature | Status | Notes |
|---------|--------|--------|
| Generate copy of page (same or other space) | todo | New slug/title; independent thereafter |
| Copy assets referenced by page | todo | Or document “copy body only” if scoped |
**Stage-1 acceptance:** member can produce an independent copy without manual
git surgery as the only path (operator git escape hatch may exist but is not
the product path).
## Explicitly later (not stage-1 blockers)
Examples — full list in `model-v0.yaml`:
- Favorites / social graph
- Marketplace (challenges, methods, solutions)
- Monetization / payments
- Full Bubble workflow automation parity
- Pixel-perfect Research chrome parity
- In-app collaborative real-time editing
## Platform dependencies (not product features)
| Dependency | Stage-1 role |
|------------|----------------|
| NetKingdom OIDC + (eventually) registration mail | Onboarding |
| apps-pg | Space/member metadata |
| Forgejo | Markdown SoR |
| Railiance deploy | Host app.coulomb.social |
## Implementation backlog (derived)
Priority order suggested for build work after this decision:
1. Space member CRUD + Title / Abstract edit
2. Visual field (space, then page) + asset storage convention
3. Page metadata (title/abstract/visual) + create/update/delete path
4. Page copy
5. Page transfer
6. Onboarding: transfer cohort process + unstick public registration residual
Bubble export/mapping (CSOC-WP-0001-T02) feeds **content migration** into these
capabilities but does not redefine the must set.
## Open product questions
1. **Visual** — cover image only, or gallery? Max size? Forgejo `assets/` vs object store?
2. **Abstract** — rename `Space.description` → abstract in UI only, or schema rename?
3. **Page body editing** — stage 1 keeps edit-in-Forgejo for body, app forms for Title/Abstract/Visual only? Or in-app markdown editor?
4. **Delete** — hard delete vs archive (`is_active`)?
5. **Transfer cohort** — require public self-registration, or LLDAP bulk invite for stage 1?

View file

@ -0,0 +1,73 @@
# Capability / feature vocabulary (coulomb-social)
Status: **adopted for product work** (2026-08-12)
Promote to fleet canon after one full cutover cycle.
Cites: orthogonal architecture Capability (C1C3, `realizes`); reuse-surface
for *cross-product* reuse only — not product feature flags.
## The coin
| Side | Name | Question |
|------|------|----------|
| **Utility** | **Capability** | What can a person *do* or *get*? Stable job-to-be-done. |
| **Implementation** | **Feature** | Which concrete product slice delivers (part of) that utility? |
Capabilities change slowly. Features appear, split, toggle, and retire under them.
## Hierarchy (depth capped)
```text
Capability
└── Feature+ (implementation slices)
└── Realization (code, config, deploy) — optional detail
└── Toggle? (runtime/config switch on a feature or stage)
```
Rules:
1. **Capabilities: few.** Target ~1030 for all of coulomb.social, not hundreds.
2. **No unlimited trees.** At most capability → optional sub-capability → feature.
3. **One feature, one primary capability.** Cross-links allowed as `supports`, not multi-parent ownership.
4. **Toggles attach to features (or release stages), never to capabilities.**
“Turn off identity” is a product decision, not a flag.
5. **Feature cut = prioritize capabilities**, then name which features are enough to call a capability *realized for that stage*.
6. **Partial rebuild is valid.** Stage N can retire Bubble as *productive* home while Bubble remains *reference-only* for later capabilities.
## Status labels
### Capability priority (cut / roadmap)
| Label | Meaning |
|-------|---------|
| `must_stage_1` | Required before user transfer + Bubble productive retirement |
| `later` | Rebuild after stage 1; not a transfer blocker |
| `out` | Explicitly not rebuilding (or only if strategy changes) |
| `platform` | Delivered by platform dependency (NetKingdom, Forgejo, …) |
### Feature implementation status
| Label | Meaning |
|-------|---------|
| `shipped` | On app.coulomb.social (or ready to enable) |
| `partial` | Exists but missing stage-1 acceptance bits |
| `todo` | Not built; required for its capability stage |
| `later` | Intentionally after stage 1 |
| `blocked` | Waiting on external dependency |
## What not to conflate
| Concept | Home |
|---------|------|
| Product capability (user utility) | This model |
| Fleet reusable capability | reuse-surface registry |
| Platform service (OIDC, Forgejo, apps-pg) | Platform deps; product *depends_on* |
| Feature toggle | Env/settings/flag on a **feature** |
| Workplan task | Execution unit; may implement many features |
## Naming
- Capabilities: `cap.<kebab>` — noun phrase of utility
e.g. `cap.space-content`
- Features: `feat.<kebab>` — verb/noun of implementation
e.g. `feat.space-md-render`
- Prefer stable ids; titles may change.