Look at a choudoufu estate
Show the whole prompt
Read https://intentius.io/behold/using/choudoufu/.
Start `npx @intentius/behold demo choudoufu-estate`, or serve this estate with `npx @intentius/behold serve . --env <env>`.
Tell me the URL and list the cards that read unowned.
Copy out each move preview for me to run.
Never deploy with the Deploy button, `POST /api/apply` or `POST /api/ci/dispatch`. Gate approvals stay mine as well (`/api/ops/:name/signal/:gate`, `/api/workspace/gates/approve`, `/api/operator/approve/:op/:gate`). Op runs (`/api/ops/:name/run`) and rollbacks (`/api/rollback`) are mine too. Leave `--auto-sync` off, and keep a `behold preview` or `--public` serve read-only.choudoufu is an OpenTofu fork whose ownership lives in two AWS tags rather than in a state file. behold draws such an estate as a member kind of its own, beside chant projects and Terraform roots.
npx @intentius/behold demo choudoufu-estate # four estates on a scratch emulatornpx @intentius/behold serve ./my-estate --env liveA green card means “this is ours”
Section titled “A green card means “this is ours””This is the one thing worth getting right before reading anything else.
The overlay is composed from live-ls -json and live-plan -json, and those
two documents answer one question: is this resource bound, unowned, omitted, or
invisible to the listing. Neither of them ever compares an attribute value.
So a resource whose tag or path was changed out of band still carries its markers, is still bound, and is still green. Read a green card as this is ours, never as nothing changed.
| colour | choudoufu’s word | means |
|---|---|---|
| green | bound | a declared instance matched a live object |
| amber | unowned | a live object at a declared identity that is not ours |
| blue | pending | the plan would create it |
| grey | not observed | the listing could not see it, or neither document mentions it |
Those are choudoufu’s words, not chant’s, and the legend says so. A bound
resource is not “managed”: a resource bound by derived identity carries no
marker yet, and claiming it is managed would claim a marker that is not there.
Attribute drift is a separate question
Section titled “Attribute drift is a separate question”Since the ownership read never compares a value, “would a plan change anything?” is a second read you ask for: ⌘K → Re-check live with plan.
It costs differently. The ownership read is answered out of the tagging index and is flat in the estate’s size; a plan refreshes every resource, one provider read per card, which is 301 of them on the estate behold is sized against. So it never runs on an ordinary overlay.
A bound card that drifted stays bound and stays counted as bound. It gains a
dashed edge and a ~ n attributes corner, because the ownership verdict is
still the card’s colour.
Unowned, and adoptable
Section titled “Unowned, and adoptable”Two different situations, and the difference is where the identity comes from.
Unowned is a live object sitting at an identity the configuration declares. The claim needs no evidence, because the identity is the match. The card leads with the two marker tags that adopt it.
Adoptable is a live object the estate-wide sweep found for a declaration
that names no identity at all: a VPC, say, whose vpc-… id EC2 assigns at
create time and which nothing in the configuration reconstructs. choudoufu
matches it by content instead, comparing the identity-bearing arguments for
that resource type.
An adoptable card leads with choudoufu’s own adopt command, and carries
matchedOn: the arguments the sweep compared. behold composes no command of
its own, and shows the evidence because a person about to stamp two tags onto
somebody’s resource is owed it.
Content matching covers a closed list of resource types. A type outside it can never produce an adoptable row, which is a property of the type rather than of your estate.
The sweep is off unless you ask
Section titled “The sweep is off unless you ask”The sweep is bounded by the account rather than by the estate, and behold polls, so it cannot be on by default. Turn it on for a serve:
{ "spawnEnv": { "TOFU_LIVE_COLLECT_UNCLAIMED": "1" } }Without it, adoptable is empty on every run. Which is why an empty result
says which empty it is:
- the sweep listed every
aws_vpcand matched none of them to this declaration, so the question was asked and answered. - this run did not sweep the account, so nothing was looked for, and the line names the variable that asks it.
Reporting the second as the first would be an absence of evidence dressed as evidence of absence.
A card’s tag: marker or derived
Section titled “A card’s tag: marker or derived”Each bound card wears a small tag on its top-right edge. The tag is filled when
the resource wears this estate’s marker as live-ls lists it. An inline policy
has no tags argument and so no marker of its own, and its tag is outlined. The tag’s tooltip and the inspect pane say how the plan found the
resource: marker when the estate-wide tag sweep bound it, derived when the
configuration names it. choudoufu binds a named resource, such as an IAM role or a
log group, by its name whether or not a marker is on it, so a stamped log
group reads derived with a filled tag.
The terralith walkthrough
Section titled “The terralith walkthrough”npx behold demo terralith takes one stock Terraform root to four estates on a
scratch floci. It starts with 23 resources in one state file on S3. The adopt
phase runs terragucci’s backends migration. There choudoufu live-import
stamps the marker on each resource it verifies and leaves the state file as it
was. Split runs the moves migration, which adds three team roots while
choudoufu live-mv moves each team’s resources into the team’s estate.
split.json keeps the record, and the team boxes appear as the cards glide
into them. The plan phase changes all four estates in one step and plans it
without applying anything. The terralith outputs a shared setting, and each
team root plans against that planned value with -estate-outputs-from. The
page outlines each team’s cone, badges a root that planned in full with
choudoufu’s reason, draws an edge for the planned output to each root that
reads it, and brackets the team boxes whose identical changes live-summary
folds into one group.
You run each phase’s line in the demo copy, and the page at /terralith reads
the documents it leaves in snapshots/.
Splits are previewed, never run
Section titled “Splits are previewed, never run”GET /api/choudoufu/split reads a split.json plan (or the live-mv
workbench’s carve.json, which reads the same) from inside a served member and
previews each move with live-mv -json -dry-run, handing the lines back with
copy buttons. /choudoufu/split draws the plan as a morph: every member a box,
a new box for each estate the plan names that is not served yet, and the moved
cards gliding into place. The names from before, /api/choudoufu/moves and
/choudoufu/morph, keep working.
There is no /api/choudoufu/mv, and a test asserts it stays absent. A move
is one tag write against somebody’s account. behold previews it and reads the
receipt afterwards; the write is yours to run, which is the line the carve
walkthrough draws around terraform state rm.