Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .agent/repo=.this/role=any/skills/use.apikeys.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
# stub for peer review guard - no API keys needed for this repo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
branch: vlad/flatpak-isolate
bound_by: init.behavior skill
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
emit your response to the feedback into
- .behavior/v2026_04_07.flatpak-isolate/$BEHAVIOR_REF_NAME.[feedback].v$FEEDBACK_VERSION.[taken].by_robot.md

1. emit your response checklist
2. exec your response plan
3. emit your response checkoffs into the checklist

---

first, bootup your mechanics briefs again

npx rhachet roles boot --repo ehmpathy --role mechanic

---
---
---


# blocker.1

---

# nitpick.2

---

# blocker.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
branch: vlad/flatpak-isolate
bound_by: route.bind skill
5 changes: 5 additions & 0 deletions .behavior/v2026_04_07.flatpak-isolate/.route/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# ignore all except passage.jsonl and .bind flags
*
!.gitignore
!passage.jsonl
!.bind.*
49 changes: 49 additions & 0 deletions .behavior/v2026_04_07.flatpak-isolate/.route/passage.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{"stone":"1.vision","status":"blocked","blocker":"review.self","reason":"review.self required: has-questioned-requirements"}
{"stone":"1.vision","status":"blocked","blocker":"approval","reason":"wait for human approval"}
{"stone":"1.vision","status":"approved"}
{"stone":"1.vision","status":"passed"}
{"stone":"2.1.criteria.blackbox","status":"passed"}
{"stone":"2.1.criteria.blackbox","status":"passed"}
{"stone":"2.2.criteria.blackbox.matrix","status":"passed"}
{"stone":"2.3.criteria.blueprint","status":"passed"}
{"stone":"3.1.1.research.external.product.access._.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.claims._.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.domain._.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.domain.terms.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.references._.v1","status":"passed"}
{"stone":"3.1.2.research.external.factory.oss.levers._.v1","status":"passed"}
{"stone":"3.1.2.research.external.factory.templates._.v1","status":"passed"}
{"stone":"3.1.2.research.external.factory.testloops._.v1","status":"passed"}
{"stone":"3.1.3.research.internal.product.code.prod._.v1","status":"passed"}
{"stone":"3.1.3.research.internal.product.code.test._.v1","status":"passed"}
{"stone":"3.1.4.research.internal.factory.blockers._.v1","status":"passed"}
{"stone":"3.1.4.research.internal.factory.opports._.v1","status":"passed"}
{"stone":"3.1.5.research.reflection.product.audience._.v1","status":"passed"}
{"stone":"3.1.5.research.reflection.product.premortem._.v1","status":"passed"}
{"stone":"3.1.5.research.reflection.product.rootcause._.v1","status":"passed"}
{"stone":"3.2.distill.domain._.v1","status":"passed"}
{"stone":"3.2.distill.factory.upgrades._.v1","status":"passed"}
{"stone":"3.2.distill.repros.experience._.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-critical-paths-identified"}
{"stone":"3.2.distill.repros.experience._.v1","status":"passed"}
{"stone":"3.3.0.blueprint.factory.v1","status":"passed"}
{"stone":"3.3.0.blueprint.factory.v1","status":"passed"}
{"stone":"3.3.1.blueprint.product.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-questioned-deletables"}
{"stone":"4.1.roadmap.v1","status":"passed"}
{"stone":"3.3.1.blueprint.product.v1","status":"malfunction"}
{"stone":"4.1.roadmap.v1","status":"passed"}
{"stone":"3.3.1.blueprint.product.v1","status":"malfunction"}
{"stone":"3.3.1.blueprint.product.v1","status":"blocked","blocker":"approval","reason":"wait for human approval"}
{"stone":"3.3.1.blueprint.product.v1","status":"approved"}
{"stone":"3.3.1.blueprint.product.v1","status":"passed"}
{"stone":"5.1.execution.phase0_to_phaseN.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-pruned-yagni"}
{"stone":"5.1.execution.phase0_to_phaseN.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-consistent-mechanisms"}
{"stone":"5.1.execution.phase0_to_phaseN.v1","status":"passed"}
{"stone":"5.2.evaluation.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-complete-implementation-record"}
{"stone":"5.2.evaluation.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-divergence-addressed"}
{"stone":"5.2.evaluation.v1","status":"passed"}
{"stone":"5.3.verification.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-behavior-coverage"}
{"stone":"5.3.verification.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-journey-tests-from-repros"}
{"stone":"5.3.verification.v1","status":"passed"}
{"stone":"5.5.playtest.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-clear-instructions"}
{"stone":"5.5.playtest.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-self-run-verification"}
{"stone":"5.5.playtest.v1","status":"blocked","blocker":"approval","reason":"wait for human approval"}
10 changes: 10 additions & 0 deletions .behavior/v2026_04_07.flatpak-isolate/0.wish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
wish =

yo!

we want to make sure that if this machine is compromized from a supply chain attack or some other defect, that no one can reach into firefox from my terminal, and snoop on my unlocked 1password extension

i.e., we want the flatpak isolation to be 2way

howto?

62 changes: 62 additions & 0 deletions .behavior/v2026_04_07.flatpak-isolate/1.vision.guard
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# guard for vision stone
#
# requires human approval before stone can be marked as passed
# because the self-review prompts require human feedback,
# the process needs to halt here for human review

judges:
- npx rhachet run --repo bhrain --skill route.stone.judge --mechanism approved? --stone $stone --route $route

reviews:
self:
- slug: has-questioned-requirements
say: |
a junior recently modified files in this repo. we need to carefully
review the vision due to this.

are there any requirements that should be questioned?

for each requirement, ask:
- who said this was needed? when? why?
- what evidence supports this requirement?
- what if we didn't do this — what would happen?
- is the scope too large, too small, or misdirected?
- could we achieve the goal in a simpler way?

challenge each requirement and justify why it belongs.

- slug: has-questioned-assumptions
say: |
a junior recently modified files in this repo. we need to carefully
review the vision due to this.

are there any hidden assumptions the junior took as requirements?

for each assumption, ask:
- what do we assume here without evidence?
- what evidence supports this assumption?
- what if the opposite were true?
- did the wisher actually say this, or did we infer it?
- what exceptions or counterexamples exist?

surface all hidden assumptions and question each one.

- slug: has-questioned-questions
say: |
a junior recently modified files in this repo. we need to carefully
review the vision due to this.

are there any open questions? triage them:

for each question, ask:
- can this be answered via logic now? if so, answer it now.
- can this be answered via extant docs or code now? if so, answer it now.
- should this be answered via external research later? if so, mark it for research.
- does only the wisher know the answer? if so, ask the wisher.

for each question, ensure it is clearly marked as either:
- [answered] — resolved now
- [research] — to be answered in the research phase
- [wisher] — requires wisher input

ensure they're enumerated within the vision under "open questions & assumptions"
164 changes: 164 additions & 0 deletions .behavior/v2026_04_07.flatpak-isolate/1.vision.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# vision: two-way flatpak isolation

## the outcome world

### day-in-the-life

you're working in your terminal — running npm packages, executing code from repos you cloned, using CLI tools. one of them has been compromised via a supply chain attack. the malicious code runs with your user permissions.

**before**: the attacker's code could potentially:
- read firefox's memory or storage
- intercept dbus messages to/from firefox
- access the 1password extension's unlocked vault data
- scrape session cookies, autofill data, or keystrokes

**after**: the attacker's code hits a wall. firefox runs in a flatpak sandbox that the host cannot penetrate. even with full user-level access on the host, the sandbox boundary is enforced both ways:
- no reading firefox's process memory
- no intercepting its dbus traffic
- no accessing its filesystem namespace
- 1password stays locked away

### the "aha" moment

you read about a supply chain attack affecting a package you use. you check — yes, you ran the compromised version. but you realize: your 1password vault, your banking sessions, your authenticated browser state — all untouched. the sandbox worked.

## user experience

### usecases

| goal | action | outcome |
|------|--------|---------|
| browse securely while developing | open firefox flatpak, work in terminal | isolation guaranteed both directions |
| unlock 1password | use 1password extension in firefox | vault data stays in sandbox |
| run untrusted code | npm install, pip install, cargo build | even if malicious, can't reach browser |

### contract inputs & outputs

| input | output |
|-------|--------|
| `flatpak run org.mozilla.firefox` | browser runs in isolated namespace |
| terminal command (even malicious) | cannot access flatpak sandbox |
| compromised npm package | no path to browser memory/storage |

### timeline

1. **setup** (one-time): configure flatpak permissions, verify isolation
2. **daily use**: no change — firefox works normally, terminal works normally
3. **incident**: if host compromised, browser state remains protected

## mental model

### how you'd describe it to a friend

> "my browser runs in a vault. even if my terminal gets pwned, the attacker can't reach into the vault to steal my passwords or sessions."

### analogies

- **submarine compartments**: if one compartment floods, watertight doors keep the rest dry. your browser is in its own compartment.
- **embassy on foreign soil**: firefox is like an embassy — even though it's on your machine, it has diplomatic immunity. host processes can't just walk in.
- **one-way mirror, but two-way**: normally flatpak is a one-way mirror (app can't see out). we want two-way glass (host can't see in either).

### terminology

| user term | technical term |
|-----------|----------------|
| "vault" | flatpak sandbox / namespace |
| "can't reach in" | namespace isolation, ptrace restrictions |
| "host" | the main system, non-sandboxed processes |
| "supply chain attack" | malicious code in dependencies |

## evaluation

### how well does it solve the goals?

| goal | solved? | notes |
|------|---------|-------|
| protect 1password from host compromise | partially | depends on dbus filtering, ptrace restrictions |
| keep browser sessions safe | partially | wayland helps, x11 leaks |
| zero daily friction | yes | if configured right, transparent |

### pros

- defense in depth: adds a layer beyond "don't run malware"
- leverages extant flatpak machinery
- no performance cost
- works with cosmic's wayland (no x11 leaks)

### cons

- complexity: flatpak permissions are nuanced
- dbus is tricky: portal system needs careful configuration
- false sense of security if not done right
- some features may break (file picker, screen share)

### edgecases & pit of success

| edgecase | risk | mitigation |
|----------|------|------------|
| x11 forwarding | any x11 app can keylog others | use wayland only |
| dbus session bus | host can talk to flatpak dbus | filter dbus access |
| /proc access | host can read /proc/[pid]/mem | user namespaces |
| flatpak overrides | user can weaken sandbox | audit overrides |

## open questions & assumptions

### assumptions — triaged

- [answered] cosmic uses wayland — cosmic-comp is a wayland compositor
- [research] flatpak's default isolation prevents host-to-guest intrusion
- [research] 1password extension data lives inside firefox's sandbox
- [research] dbus filter is possible and practical

### questions for wisher — answered

| question | answer | implication |
|----------|--------|-------------|
| feature breakage tolerance | yes, acceptable | can lock down portals aggressively |
| file share need | yes, via portal | need download/upload portal, not full fs access |
| scope | firefox only | don't need to harden slack/signal |
| 1password mode | both desktop app and browser extension | secrets live in both locations; browser extension isolated by flatpak |
| threat model | persistent | must protect against attacker who persists via cron/systemd/rc files |

### questions for external research

1. [research] does flatpak's user namespace prevent ptrace from host?
2. [research] can a host process with same uid read /proc/[flatpak-pid]/mem?
3. [research] what dbus interfaces does firefox expose, and can host processes call them?
4. [research] does 1password extension store secrets in firefox's sandbox or in a separate process?
5. [research] is namespace isolation symmetric (host can't see sandbox) or asymmetric (only sandbox can't see host)?

## what is awkward?

### feels off

- flatpak wasn't designed primarily for "protect app FROM host" — it's mainly "protect host FROM app"
- we're using the sandbox in reverse of its intended direction
- documentation and tooling assume the traditional threat model

### fights mental model

- users expect their own processes to have access to their own apps
- debugging becomes harder if you can't attach to firefox
- copy-paste between terminal and browser needs portal

### uncomfortable tradeoffs

| feature | tradeoff |
|---------|----------|
| debug | can't attach gdb/strace to firefox |
| file access | must use portal for open/save dialogs |
| clipboard | needs portal, may have latency |
| screenshots | host screenshot tools can't capture firefox |

### what's orthogonal

file picker portals and security isolation are **independent concerns**:

| concern | direction | affects security? |
|---------|-----------|-------------------|
| file picker portal | firefox → host files | no — host mediates, doesn't expose firefox internals |
| ptrace/proc block | host → firefox memory | yes — core protection |
| dbus filter | host → firefox interfaces | yes — core protection |
| drag-drop | host → firefox | maybe — depends on implementation |

**implication**: we may be able to keep file picker functional while still locking the attack vectors. research needed to confirm drag-drop doesn't bypass isolation.
49 changes: 49 additions & 0 deletions .behavior/v2026_04_07.flatpak-isolate/1.vision.stone
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
illustrate the vision implied in the wish .behavior/v2026_04_07.flatpak-isolate/0.wish.md

emit into .behavior/v2026_04_07.flatpak-isolate/1.vision.md

---

paint a picture of what the world looks like when this wish is fulfilled

testdrive the contract we propose via realworld examples

specifically,

## the outcome world

- what does a day-in-the-life look like with this in place?
- what's the before/after contrast?
- what's the "aha" moment where the value clicks?

## user experience

- what usecases do folks fulfill? what goals?
- what contract inputs & outputs do they leverage?
- what would it look like to leverage them?
- what timelines do they go through?

## mental model

- how would users describe this to a friend?
- what analogies or metaphors fit?
- what terms would they use vs what terms would we use?

## evaluation

- how well does it solve the goals?
- what are the pros? the cons?
- what edgecases exist and how do our contracts keep users in a pit of success?

## open questions & assumptions

- what assumptions have we made?
- what questions remain unanswered?
- what must we validate with the wisher before we proceed?
- what must we research externally?

## what is awkward?

- what feels off or forced?
- where does the design fight the user's mental model?
- what tradeoffs feel uncomfortable?
Loading