# ash_phoenix — extraction record shapes

**Mechanical front-end available**: `../witness.py` (tree-sitter)
extracts this platform deterministically — resources, router, secrets.
Prefer it wherever python + pip are available; this guide remains the
contract (and the LLM fallback's instructions). The records it emits
are quote-verified by the instrument exactly like agent extraction.

Platform-specific half of `../extraction.md` (the generic law — quote
everything, one file per record, honesty rules — lives there and
binds here too).

## An Ash resource file

```json
{
  "file": "lib/teamology/rosters/resources/guardian.ex",
  "module": "Teamology.Rosters.Guardian",
  "store": "guardians",
  "store_quote": "table \"guardians\"",
  "columns": [
    {"name": "first_name", "quote": "attribute :first_name, :string"},
    {"name": "email", "quote": "attribute :email, :string"}
  ],
  "belongs_to": [
    {"name": "student", "quote": "belongs_to :student, Teamology.Rosters.Student"}
  ],
  "policies": {
    "present": false,
    "quote": "use Ash.Resource,",
    "default_deny": null,
    "admit_kinds": [],
    "bypass": false
  },
  "actions": {
    "defaults": ["read", "create", "update"],
    "defaults_quote": "defaults [:read, :create, :update]",
    "destroy": false,
    "archive": false,
    "redaction": [
      {"name": "redact_message_content", "sets": ["utterance"],
       "quote": "change set_attribute(:utterance, \"[redacted]\")"}
    ]
  },
  "domain_registered": false
}
```

- `store` — the `postgres do table "…"` name (or the AshPostgres
  default). Non-resource `.ex` files (contexts, LiveViews, workers)
  get a record with no `store` key and whatever facts apply — usually
  none; `{"file": …}` alone is a valid "nothing witnessed here"
  record.
- `columns` — every `attribute`/`uuid_primary_key`/timestamp column,
  each quoting its declaring line. Do not classify; the instrument
  derives person-signals from the platform profile's regex.
- `policies.present` — a `policies do` block exists; `default_deny`
  (terminal `forbid_if always()` or equivalent), `admit_kinds`
  (short strings naming what each `authorize_if` admits, each from a
  quoted line), `bypass` (any `bypass` block). When absent, quote the
  `use Ash.Resource` line — proof you read the file.
- `actions.redaction` — actions matching
  `redact|scrub|purge|expunge|anonymi`, with the columns they set.
  `destroy`/`archive` — a destroy action / an `archived_at`-style
  column or archive action.
- `domain_registered` — listed in the domain module's `resources do`
  block? (Read the domain file — the `.ex` directly above
  `resources/`; null if you did not.)

## The router

```json
{"file": "lib/teamology_web/router.ex", "router": {"pipelines": [
  {"name": "browser", "plugs": ["fetch_session", "load_from_session"],
   "quote": "pipeline :browser do"}
]}}
```

## Runtime config (secrets census)

```json
{"file": "config/runtime.exs", "secrets": [
  {"name": "SECRET_KEY_BASE", "quote": "System.get_env(\"SECRET_KEY_BASE\")"}
]}
```

Every `System.get_env`/`System.fetch_env!`/Hush secret read.
