Session summary, branch inventory, push instructions, v1.1.8
follow-ups, and pickup-on-new-machine smoke commands. Main is at
v1.1.7 (5cbb6ca); seven minor releases shipped this session via
the dispatch-and-review workflow.
Read this first on the new machine.
16 KiB
Handoff — 2026-06-05
Machine-switch handoff. This document is the entry point for picking up PiCloud work on a different machine. It captures session state, what shipped, what's queued, and how to continue.
TL;DR
mainis at v1.1.7 — seven minor releases (v1.1.1 → v1.1.7) shipped this session via the dispatch-and-review workflow.- Working tree is clean.
- Next release is v1.1.8 (User Management). A draft dispatch prompt is sketched in §6 below; ready to send to a dev agent.
- One dev Postgres container (
picloud-postgres-1on port 15432) is still running on the source machine — tear it down withdocker compose down -vbefore the source machine goes offline.
How to resume on the new machine
git clone https://git.mc02.dev/fabi/PiCloud.git
cd PiCloud
git checkout main
git log --oneline -10 # should show v1.1.7 reviewer commit at HEAD
docker compose up -d # local Postgres for DB-gated tests
export DATABASE_URL='postgres://picloud:picloud@127.0.0.1:5432/picloud'
cargo test --workspace -- --test-threads=2
If you're starting from this branch (handoff/2026-06-05), it points at
the same main HEAD with this HANDOFF.md added; merge or just read it
and continue work on main.
For the master encryption key needed by v1.1.7+ secrets:
export PICLOUD_SECRET_KEY="$(openssl rand -base64 32)"
# OR, for dev only:
export PICLOUD_DEV_MODE=true
The dev fallback uses a deterministic key (SHA-256 of a hardcoded
string) — fine for local testing, fatal for any real deployment.
Session summary: v1.1.1 → v1.1.7
All seven minor releases completed in one session via the dispatch
workflow you set up: I draft a prompt, you dispatch it to a fresh
agent in another session, the agent implements and writes HANDBACK.md,
you bounce the report back to me, I audit the branch and write
REVIEW.md with a verdict, you bounce-back-for-fixes-if-needed, and on
approve I fast-forward merge into main.
| Release | Capability | Iterations | Status |
|---|---|---|---|
| v1.1.1 | Storage & Events (KV + triggers framework + outbox + dispatcher + NATS-style sync HTTP + dead-letter table + dashboard surface) | 1 | ✅ merged |
| v1.1.2 | Documents (docs::* SDK + query DSL + docs:* triggers) |
2 | ✅ merged (iteration 2 fixed a fmt diff) |
| v1.1.3 | Modules (scripts.kind + PicloudModuleResolver + AST caches + script_imports) |
1 | ✅ merged |
| v1.1.4 | Outbound HTTP & Scheduled Tasks (http::* with SSRF deny-list + cron triggers) |
1 | ✅ merged |
| v1.1.5 | Files & Pub/Sub (filesystem-backed blobs + pubsub::publish_durable + first CI workflow) |
1 | ✅ merged |
| v1.1.6 | Realtime Channels & Client Library (SSE + topics + HMAC subscriber tokens + @picloud/client@1.0.0) |
1 | ✅ merged |
| v1.1.7 | Configuration & Email (encrypted secrets + outbound/inbound email + dead-letter handler fix) | 1 | ✅ merged |
Versioning state on main:
- Workspace
1.1.7 - SDK schema
1.8 - Dashboard
0.13.0 @picloud/client1.0.0- Migrations applied through
0025
Test counts at HEAD: cargo test --workspace --test-threads=2 with
DATABASE_URL set → 617 passed / 0 failed. The --test-threads=2
is required on shared dev Postgres (~9 concurrent build_apps
otherwise exhaust connections); CI's dedicated Postgres doesn't hit
this.
Branches on this machine
v1.1.x feature branches (all merged into main, kept locally for traceability)
| Branch | HEAD | What it contains |
|---|---|---|
feat/v1.1.1-storage-and-events |
2796f36 |
v1.1.1 work + HANDBACK + REVIEW |
feat/v1.1.2-documents |
5bbbc26 |
v1.1.2 work (2 iterations) + HANDBACK + REVIEW |
feat/v1.1.3-modules |
6f17259 |
v1.1.3 work + HANDBACK + REVIEW |
feat/v1.1.4-http-cron |
03d03ea |
v1.1.4 work + HANDBACK + REVIEW |
feat/v1.1.5-files-pubsub |
d064681 |
v1.1.5 work + HANDBACK + REVIEW |
feat/v1.1.6-realtime-client |
64ad978 |
v1.1.6 work + HANDBACK + REVIEW |
feat/v1.1.7-secrets-email |
5cbb6ca |
v1.1.7 work + HANDBACK + REVIEW |
All seven HEADs are reachable from main (fast-forward merges). Keeping
the branches makes it easy to inspect the per-release commit slice
without git log filtering.
Older branches predating this session (state uncertain)
These appeared in git branch at session start and weren't touched by
v1.1.x work. I don't know which are abandoned, in-flight, or already
merged under different names. On the new machine, decide for each:
| Branch | Last commit | Tracking |
|---|---|---|
chore/ui-hardening |
b42e273 fix(test): admin_is_implicit_app_admin uses force=true on app delete |
local-only |
feat/app-members |
e6fc6e6 test(picloud): close two app_members test gaps |
local-only |
feat/cli |
5d08974 style(cli): re-fmt one stray format! line in the integration test |
tracks origin/feat/cli (up to date) |
feat/multi-app-scoping |
a393f11 feat(dashboard): auto-slug app names and infer route host kind from input |
tracks origin/feat/multi-app-scoping (ahead 3) |
feat/users-and-keys-ui |
6eb32a7 feat(dashboard): adopt ActionMenu for user row actions |
local-only |
feat/users-authz |
2aab92a style: cargo fmt across Phase 3.5 changes |
local-only |
test/cli-journeys |
e4851b3 test(cli): extract shared Fixture into tests/common |
tracks origin/test/cli-journeys (up to date) |
test/frontend-e2e |
ec3c768 test(dashboard): add full-stack integration specs |
local-only |
Push these if you want them mirrored on the new machine — see §3 below for the push commands. If any are obsolete, delete them locally before resuming.
§3 — Push instructions
Push was denied in this session (sandbox restriction). Run these on the
source machine to mirror state to origin:
# 1. The v1.1.x releases on main (55 commits)
git push origin main
# 2. The seven v1.1.x feature branches (preserves per-release history)
git push origin feat/v1.1.1-storage-and-events
git push origin feat/v1.1.2-documents
git push origin feat/v1.1.3-modules
git push origin feat/v1.1.4-http-cron
git push origin feat/v1.1.5-files-pubsub
git push origin feat/v1.1.6-realtime-client
git push origin feat/v1.1.7-secrets-email
# 3. This handoff branch
git push -u origin handoff/2026-06-05
# 4. OPTIONAL — push the older branches you want on the new machine
# (decide per-branch; some may be abandoned)
git push origin chore/ui-hardening
git push origin feat/app-members
git push origin feat/multi-app-scoping # ahead 3 of remote
git push origin feat/users-and-keys-ui
git push origin feat/users-authz
git push origin test/frontend-e2e
After pushing, on the new machine: git fetch --all brings everything
down. git checkout main puts you at v1.1.7 HEAD.
§4 — Workflow context (read before dispatching v1.1.8)
The dispatch-and-review workflow you've been using:
- You ask me to draft the dispatch prompt for the next release.
- I draft the prompt based on:
- The roadmap in
docs/v1.1.x-design-notes.md§7 - Three or so follow-ups identified in the prior release's REVIEW.md
- Discipline lessons carried forward from prior retros
- The roadmap in
- You dispatch the prompt to a fresh agent in another session — that agent gets no prior conversation context; the prompt + the docs it points at are everything they have.
- The agent implements + writes
HANDBACK.mdat the repo root, then stops. - You bounce the HANDBACK back to me.
- I audit the branch and write
REVIEW.mdwith a verdict (APPROVEorNEEDS CHANGES). - If
NEEDS CHANGES: you bounce the REVIEW back to the agent; they iterate; back to step 5. - If
APPROVE: I fast-forward merge the branch intomainand pause for your next instruction.
What's worked well across seven releases:
- The discipline reminders compound. Each release's retro identifies
one small habit the agent dropped (§8 attestation hand-counting,
silent prompt-default deviations, brief-internal contradictions
silently reinterpreted, clippy run without
--all-targets); the next release's prompt explicitly addresses it. By v1.1.7 the agent was catching their own latent findings without prompting. - Explicit "deviations beyond the brief" sections in HANDBACK make audits fast — every meaningful judgment call is in one place.
- The "this is the deferrable piece under scope pressure" clause in big releases (v1.1.6 client lib, v1.1.7 inbound email) gave the agent a clean escape hatch they never actually needed but worked as intended.
- Latent findings discovered during implementation (v1.1.3 cross-app trigger gap, v1.1.4 SSRF literal-IP bypass, v1.1.6 dead_letter handler never firing, v1.1.7 clippy regression at v1.1.6 HEAD) all surfaced honestly rather than being silently worked around.
What to do differently in v1.1.8:
- Walk through each code example in the prompt before sending. v1.1.4
brief said
(url, opts)but its example washttp::post(url, body)— the agent had to fix it during implementation. v1.1.7 brief sketchedTriggerEvent::DeadLetterfield names that didn't match the actual variant. Both flagged correctly, but pre-resolution saves agent effort. - Pin the clippy gate:
cargo cleanbeforecargo clippy --all-targetsto defeat incremental-cache false-greens. See v1.1.7 REVIEW §3.3 for context.
§5 — Pending follow-ups for v1.1.8
From the v1.1.7 REVIEW.md, three load-bearing items to fold into the v1.1.8 dispatch prompt:
5.1 Drop the plaintext realtime_signing_key column
The v1.1.7 phase-2 commitment. v1.1.7 added NULL-able encrypted columns
- DROP NOT NULL on the plaintext column; the startup task encrypts existing rows. v1.1.8 drops the plaintext column entirely.
Pre-flight check: scan for any remaining non-NULL rows on the plaintext column. If found, run the encryption migration before the drop. If the v1.1.7 startup task ran on the operator's deploy, all rows should already be encrypted.
CHANGELOG must note that v1.1.8 requires v1.1.7 to have been applied first. No skipping versions.
5.2 Clippy --all-targets discipline refinement
The v1.1.7 audit caught a real regression: four warnings predated v1.1.7 that the v1.1.6 audit reported as clippy-green. Likely cause: cargo's incremental cache leaving test binaries unchecked.
v1.1.8 prompt should require either:
cargo cleanbeforecargo clippy --all-targets, OR- Explicit verification that the clippy output includes
Checkinglines for test crates.
CI's .github/workflows/ci.yml (added in v1.1.5) might also benefit
from a clippy-cache-check step.
5.3 auth_mode = 'session' for realtime subscriber tokens
v1.1.7's CHECK constraint on topics.auth_mode only allows
('public', 'token'). v1.1.8's users::* work needs to:
- Extend the CHECK to include
'session'. - Add a session-token validator alongside the existing HMAC validator
behind the unchanged
RealtimeAuthoritytrait.
The trait shape from v1.1.6 already supports this — natural extension.
§6 — Draft v1.1.8 dispatch prompt outline
Not the full prompt — just the scope sketch so you can ask me to expand it on the new machine.
v1.1.8 — User Management (users::*)
Core scope:
users::create / get / find / update / delete / listSDK- Password hashing (argon2id)
userstable per-app- Sessions:
users::login(email, password)→ returns a session token;users::verify(session_token)returns the user or() - Sessions table with TTL + revocation
- Email verification flow (uses v1.1.7 email::send)
- Password reset flow (uses v1.1.7 email::send + tokens)
- Invitations (admin creates an invite → email link → user accepts + sets password)
- Roles: per-app role assignments on users
Capability::AppUsersRead/Write/Adminmapped to existing scopes- Dashboard: Users tab on app detail page (list, invite, role-edit)
Follow-ups from v1.1.7 retro (fold in):
- Drop plaintext
realtime_signing_keycolumn (phase-2) - Clippy
--all-targetsdiscipline refinement auth_mode = 'session'for realtime subscriber tokens (uses v1.1.8 sessions)
Out of scope:
- OAuth providers (defer to v1.2+)
- 2FA / MFA (defer to v1.2+)
- SSO / SAML (defer)
- Password policy customization (defer; ship with sensible default)
- User-to-user messaging (defer; userland)
Ask me to expand this into a full prompt when you're ready.
§7 — Environmental notes
- Dev Postgres container
picloud-postgres-1(port 15432) was running at session end on the source machine. The v1.1.5/v1.1.6/ v1.1.7 agents started it for live DB-gated tests. Tear down withdocker compose down -vbefore the source machine goes offline if you want a clean state. PICLOUD_SECRET_KEYis required for v1.1.7+ to start. Pick one withopenssl rand -base64 32for production; usePICLOUD_DEV_MODE=true(no master key needed) for local development. The dev key is deterministic so secrets persist across restarts in dev.- CI workflow lives at
.github/workflows/ci.yml(added in v1.1.5). Runs fmt + clippy +cargo test --workspaceagainst apostgres:15service, plus dashboardnpm run check. When you push tomainor open a PR, CI will run. First push after this handoff will exercise it for the first time on real workload — watch the run.
§8 — Key documents for orientation
CLAUDE.md— project conventions. Read first.serverless_cloud_blueprint.md— the authoritative architecture document.docs/sdk-shape.md— SDK conventions every v1.1.x service follows.docs/v1.1.x-design-notes.md— the in-flight-decisions document. Sections §1–§6 contain the "Decided 2026-06-01" annotations from the design conversation that preceded this session; §7 holds the v1.1.x roadmap; §1–4 are candidates for pruning (their decisions shipped in v1.1.1).docs/versioning.md— patch-bump policy under the post-1.0 expansion-phase carve-out.docs/git-workflow.md— trunk-based workflow conventions.CHANGELOG.md— release notes for v1.1.1 onward. v1.1.7's entry includes the retroactive dead_letter security note.
Per-release artifacts on main:
HANDBACK.mdat repo root — currently holds the v1.1.7 agent's handback. Overwritten each release.REVIEW.mdat repo root — currently holds the v1.1.7 reviewer's audit. Overwritten each release.
If you want the full per-release HANDBACK + REVIEW history, the seven
feat/v1.1.x-* branches preserve them (each branch's HEAD~1
contains the HANDBACK and HEAD contains the REVIEW for that release).
§9 — Quick smoke after resuming
After cloning + setting up the new machine:
# Basic gates
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --workspace
# DB-gated (needs Postgres)
docker compose up -d
export DATABASE_URL='postgres://picloud:picloud@127.0.0.1:5432/picloud'
export PICLOUD_DEV_MODE=true
cargo test --workspace --test-threads=2
# Dashboard
cd dashboard && npm install && npm run check
# Client library
cd clients/typescript && npm install && npm run lint && npm run test && npm run build
If all green: machine is ready. Resume v1.1.8 work by asking me for the full dispatch prompt.
Handoff written 2026-06-05. Main HEAD: 5cbb6ca (v1.1.7 reviewer
APPROVE).