Skip to content

design(pm-stack): durability & host independence — stack state in backed-up durable storage, stack survives the laptop being off #1258

Open
0 of 3 issues completed

Description

@dezren39

Part of epic #1184 (PM stack coherence — ideal-system design series, 2026-10-26).

Why

The stack lives on one laptop: aggregator-local JSON files hold the comment store and session registry, Grist/Kaneo data lives in laptop containers, and if the laptop is off or dies, the PM system of record is gone with it. The ideal stack keeps its state in backed-up durable storage, can run from a second host or the cluster, and proves recoverability with restore drills — the PM system should be at least as durable as the work it tracks.

Design questions to answer

  • State inventory: every store (comments, registry, Grist doc, Kaneo Postgres, Pad data, feed/snapshots, Project is GitHub-side) classified by owner, backup method, and acceptable loss.
  • Target home: Turso/Supabase/Postgres-on-cluster vs replicated files — which store goes where, and what stays laptop-local by design?
  • Failover shape: second-host warm standby, cluster deployment, or cold restore — what RTO/RPO does Drew actually need for a PM dashboard?
  • Restore drills: what is restored, how often, and how is a drill result recorded so 'backed up' is a verified fact, not a hope?
  • Secrets and identity in a moved stack: SOPS/Bitwarden flow per host, and how the single-URL/Access entry follows the stack.

Acceptance

Acceptance criteria

  • A design note answering every question listed under "Design questions to answer" is landed in the repo doc/ tree and linked from this issue.
  • Implementation issues are filed and linked as sub-issues of epic epic(dashboard): PM stack coherence - single-URL, fresh data, triage-able, hierarchical #1184 (developing-today/code), each with its own acceptance criteria — this design issue does not itself carry implementation work.
  • Every open question that needs Drew is named explicitly in the design note (not buried in prose).
  • Every state store in the inventory gets a named target home, backup method, and acceptable-loss figure; RTO/RPO targets for the PM stack are stated as numbers Drew can accept or adjust.

Activity

  1. added
    kind/featureNew feature or capability request
    app/pm-stackpm-stack (Pad/Grist) in developing-today/code
    on Oct 27, 2026
  2. developing-today commented on Oct 27, 2026

    @developing-today
    Contributor
  3. added
    source/humanFiled directly by a human
    priority/normalOrdinary priority (the default)
    effort/mMedium: expected under 1 day of work
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 28, 2026
  4. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    Intake review

    Fleet-monitor intake pass (2026-10-28T02:40:00Z): this issue was missing a priority/* label and/or the standard ## Acceptance criteria section and was not yet meta/enriched. The criteria section has been appended to the body (original text preserved verbatim above it) and labels normalized.

    Related: Epic: #1184 (PM stack coherence design series). Siblings in the same series were intake-enriched in prior monitor runs (#1264–#1277).

    Notes: Design-series issue (durability & host independence), filed 2026-10-27 by Drew as part of the #1184 batch; body is well-formed (Why + design questions + its own Acceptance section). Still live: merged-PR search this run returns only unrelated PRs whose text coincidentally contains the number — none resolves or implements this design.

    Risks: Design-only stall risk (see tail).

    Suggested approach: This is one of the #1184 PM-stack coherence design series; its own "Acceptance" section already states the bar (design note in doc/ + implementation sub-issues), and the appended criteria restate that in the fleet's standard heading so the monitor and queue can gate on it. Risks: design-only items can sit silently — per house rules a design with no implementation link is flagged by the next sweep, so the follow-through that matters is the sub-issue filing, not the note alone. Suggested approach: answer the design questions against the current aggregator/orchestrator code (cite file:line), land the note, file the implementation sub-issues in the same pass.

    🤖 Agent note · state: handed off

    • Agent: fleet monitor (repo-fleet-monitor)
    • Session / ID: repo-fleet-monitor run 2026-10-27 21:19 CDT
    • Found via: monitor reconciliation (intake enrichment duty)
    • Task: Intake enrichment — acceptance criteria appended, labels normalized, this review posted; the item itself is not being worked by the monitor.
    • Expectation: unenriched → enriched; routing/work happens through the normal queue/sweep paths.
    • Links: n/a
  5. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · triaged — CONFIRMED; follow-up task 4958 enqueued

    • Agent: repo-worker-code (lane A)
    • Session / ID: queue task 2516 (triage) → follow-up task 4958
    • Verified at main efc4e18 (2026-11-01):
      • pm-stack/aggregator/src/config.ts:74,76 — comments and registry stores are plain JSON files (comments.json, registry.json, env-overridable paths); config.ts:20-21 calls the registry file the durable store, merged on every read (sources/live.ts:657 mergeIntoRegistry).
      • Live probe: the running stack's state sits in ~/.local/state/pm-aggregator/ on the laptop — actions.json, comments.json, registry.json, fleet-feed.json, snapshots/.
      • pm-stack/compose.yml — Kaneo (ghcr.io/usekaneo/kaneo:2.47.0) on postgres:16-alpine with a local named volume; Grist is part of the same laptop deployment.
      • pm-stack/README.md:291-292 — the only backup story in the repo is a manual pg_dump instruction for Kaneo; no automated backup and no restore drill covers comments/registry/Grist.
    • Routing: task 4958 (small_fix) — write the design note in doc/ answering every design question here (per-store target home, backup method, acceptable loss; numeric RTO/RPO; restore-drill design; secrets/identity per host; a dedicated Drew-questions section) and file the implementation issues as sub-issues of epic epic(dashboard): PM stack coherence - single-URL, fresh data, triage-able, hierarchical #1184. This issue stays open as the tracker.
  6. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed on Nov 1, 2026
  7. 6 remaining items

  8. added a commit that references this issue on Nov 2, 2026
  9. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 3, 2026
  10. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged (coverage pass)
    Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
    Found via: coverage pass 2026-11-03

  11. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · escalated

    Triage verdict (2026-11-03, task 7677): design acceptance MET; escalating the design's own Drew questions

    Fresh verification this shift (gh, current main):

    Why escalated (user/escalated): the design deliberately proposes, but cannot settle, these decisions — they are Drew's, and issue #3989's cutover waits on them:

    1. RTO/RPO targets — accept 4h core-stack RTO; 15m RPO for aggregator actions/comments/identity; 1h for Kaneo + canonical usage/link records; 24h for Grist/Pad/Project export? (Ramification: these numbers set backup frequency and drill pass/fail.)
    2. Canonical DB homes — dedicated cluster PostgreSQL for Kaneo + cluster persistent volumes for Grist/Pad, with aggregator state to Supabase muse-dev2 (consistent with the recorded decision on issue Long-term: migrate the pm stack into Supabase — refactor component state into schemas for central management #3142)? Or Supabase-host some of Kaneo/Grist/Pad too?
    3. Backup destinations/retention — keep local + R2 + Drive for every stateful service; what off-machine retention?
    4. Failover posture — tested cold restore within 4h, or warm standby (more complexity, single-writer fencing)?
    5. Restore evidence — approve doc/pm-stack/restore-drills/YYYY-MM.md with monthly rotating / quarterly full / annual laptop-off drills?
    6. Project export retention (issue pm-stack: make Project #4 auditable — scheduled export of fields, views, item counts, status/area distribution #1218) and 7. any intentional laptop-local exceptions.

    My recommendation (worker review, per the user/review rule): accept Q1 as proposed; Q2 as proposed (it follows Drew's #3142 Supabase-first ruling and keeps service-owned DBs service-owned); Q4 cold restore — GitHub stays usable as degraded mode, so warm standby's complexity buys little; Q5 approve as proposed. Q3/Q6/Q7 need Drew's retention/exception calls specifically.

    Until Drew answers, issue #3989 should not start cutover; issue #1514/issue #3869 backup-correctness work is NOT gated by these answers and can proceed independently.

  12. added
    user/escalatedQueue or user escalation state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  13. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    Owner ruling (Drew, 2026-11-03, via chat): all in Supabase.

    • Q2 (where the databases live): SUPERSEDED by this ruling — all PM-stack state goes to Supabase muse-dev2, not the proposed split. Kaneo, Grist, and Pad state join the aggregator state in Supabase; no dedicated cluster PostgreSQL and no cluster persistent volumes as the system of record for these services.
    • Q7 (laptop-local exceptions): none. Nothing is intentionally laptop-only; everything must be recoverable from Supabase if the laptop is lost.

    Still open on this issue: Q1 (recovery targets), Q3 (off-machine backup retention), Q4 (failover posture), Q5 (restore-drill evidence), Q6 (Project export retention). The #3989 cutover should treat Q2/Q7 as settled per above and surface any service whose storage model cannot literally live in Supabase Postgres (e.g. file-based document stores) as an explicit mapping in the cutover plan rather than a silent exception.

  14. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    Owner ruling (Drew, 2026-11-03, via chat): the recommendations are accepted.

    • Q1 (recovery targets): ACCEPTED as proposed — 4h recovery time for the core stack; 15-minute max data loss for aggregator actions/comments/identity; 1h for Kaneo + canonical usage/link records; 24h for Grist/Pad/Project export.
    • Q4 (failover posture): ACCEPTED — tested cold restore within 4h (GitHub remains the degraded mode meanwhile); no warm standby.
    • Q5 (restore-drill evidence): APPROVED as proposed — drills recorded in doc/pm-stack/restore-drills/YYYY-MM.md, monthly rotating / quarterly full / annual laptop-off.

    (Q2 and Q7 were settled by the earlier all-in-Supabase ruling, comment 6607071220.) Still open on this issue: Q3 (off-machine backup retention) and Q6 (Project export retention) — the #3989 cutover remains gated on those two only.

  15. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Owner ruling (Drew, 2026-11-03, via chat): retention decided.

    All seven design questions are now settled (Q1/Q4/Q5 accepted 2026-11-03, comment 6607099664; Q2/Q7 settled by the all-in-Supabase ruling, comment 6607071220; Q3/Q6 here). The #3989 host-independence cutover is ungated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/mMedium: expected under 1 day of workkind/featureNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/humanFiled directly by a humantask/triageQueue packet kind: verify, reproduce, and route this itemuser/escalatedQueue or user escalation state

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions