cadrumo.core.storage_taxonomy module¶
The typed authority for every application-chosen on-disk location.
Where a byte lands used to be decided by four mutually unaware authorities: an
untyped dict[str, str] in the settings module, bare string constants in the
persistence namespace registry, module-local constants in application and
entrypoint modules, and unpinned inline copies of the registry’s own names. A
name declared in the adapter layer could not be imported by core without
inverting the hexagonal direction, so the duplicates were unfixable where they
sat. This module is the single declaration all of them collapse onto: every
application-chosen name lives here, in core, and the adapter layer consumes
it downward.
Six axes ride on each member because a bare name cannot carry them:
the literal POSIX relative subpath, verbatim as it exists on disk;
StorageNodeKind, so file-versus-directory is a type-level fact rather than a guess made from a field-name suffix – a guess cannot reach the per-bucket file names no suffix convention governs, and would put a directory exactly where a document must be written;StorageScope, becauseblobsandauditeach legitimately name both a top-level category and a per-bucket subdirectory at a different depth, so members are identified by scope and name together;StorageOverridePolicy, so the guarantee that an operator cannot relocate a keystore out from under the bucket it unlocks is declared data rather than an accident of which module a constant sat in;StorageLifecycleandStorageGrouping, the conceptual classifications that answer what may be reclaimed and what belongs together;FingerprintParticipation, an independent third axis that no union of the other two reproduces, governing what the drift fingerprint covers.
The conceptual grouping has no effect on the resolved path. cache/ is the
sole on-disk category prefix and remains so: the encrypted-state substrate, the
diagnostic logs, and the durable outputs keep bare, self-describing leaf names.
See also
SettingsCentral settings aggregate whose path fields these members name.
storage_path()Resolver for a root-scoped member.
bucket_scoped_storage_path()Resolver for a bucket- or keystore-scoped member.
- class StorageNodeKind(*values)[source]¶
Bases:
StrEnumWhether a member names a directory or a single file.
Declared rather than inferred. A name-suffix heuristic cannot reach the per-bucket file names –
manifest.toml,.lock, the keystore sidecars – that follow no suffix convention, and inferring wrongly creates a directory where a document belongs, which fails much later at the write.A second enum names the same axis one layer out: the storage adapter’s
StoragePathKindanswers a wider question, adding a member for a row living in the encrypted database rather than on disk and one for content-addressed blob content. The two are deliberately not merged –coremust not import an adapter type, and aStrEnumcarrying members cannot later be extended to subclass another – so the relationship is a declared parity rather than a shared definition:DIRECTORYandFILEmust spell their values identically on both sides. Both areStrEnum, so code compares them by value across the boundary and a divergent spelling would returnFalserather than raising. A gate pins that overlap, and pins only the overlap, so the adapter stays free to grow memberscorehas no use for.- DIRECTORY¶
- FILE¶
- class StorageScope(*values)[source]¶
Bases:
StrEnumThe anchor a member’s subpath is relative to.
Scope is a required part of a member’s identity, not a decoration: the top-level
blobsandauditcategories share their names with per-bucket subdirectories at a different depth, and both are correct. Keying on name alone would conflate them.The keystore anchor is a second, independent bucket-id-parameterized root, not a nested subdirectory of the bucket it unlocks. Production states this as the load-bearing invariant it is (
validate_keystore_separation()): the keystore lives at<root>/keystore/<bucket-id>/, sibling tobuckets/, and a configuration that resolves it underbuckets/is refused so a later unlock cannot silently violate the separation.KEYSTORE_ROOTnames that per-bucket keystore directory itself – parameterized by a bucket id likeBUCKET_RELATIVE, but anchored at<root>/keystore/rather than<root>/buckets/– andKEYSTORE_RELATIVEnames what nests beneath it.- ROOT¶
- BUCKET_RELATIVE¶
- KEYSTORE_ROOT¶
- KEYSTORE_RELATIVE¶
- class StorageOverridePolicy(*values)[source]¶
Bases:
StrEnumWhether an operator may relocate a member.
The bucket and keystore layout is deliberately fixed. An operator must not be able to move a keystore out from under the bucket it unlocks, and that guarantee is expressed here as data so it can be read and enforced, rather than resting on which module a constant happened to sit in.
- OPERATOR_OVERRIDABLE¶
- FIXED¶
- class StorageLifecycle(*values)[source]¶
Bases:
StrEnumHow a member’s contents are bounded over time.
Governs what a reclaim operation may delete.
UNBOUNDED_BY_DESIGNcovers the substrate a filing is defended with: growth is the point, and pruning it would destroy evidence.- UNBOUNDED_BY_DESIGN¶
- RETENTION¶
- ROTATION¶
- TTL¶
- class StorageGrouping(*values)[source]¶
Bases:
StrEnumThe conceptual family a member belongs to.
Purely a classification for operator-facing presentation and reclaim grouping. It has no effect on the resolved path, so a member grouped as a cache need not sit under the
cache/prefix and several do not.- STATE¶
- LOGS¶
- CACHE¶
- EXPORTS¶
- class StorageArea(*values)[source]¶
Bases:
StrEnumStable operator vocabulary for the four aggregate storage families.
- STATE¶
- LOGS¶
- CACHE¶
- EXPORTS¶
- class StorageCustodyProfile(*values)[source]¶
Bases:
StrEnumPortable-profile custody depth selected by application policy.
- FULL¶
- STRUCTURED¶
- class FingerprintParticipation(*values)[source]¶
Bases:
StrEnumWhether writes beneath a member move the data-root drift digest.
An independent axis, never derived. Measured against every candidate, no expression over lifecycle or grouping reproduces the shipped set, and three candidates differ in both directions at once – omitting members that are excluded while adding members that are not. Getting it wrong is invisible in both directions: excluding too much walks the digest toward the empty-tree constant that once defeated drift detection outright, and excluding too little churns it on every cache write until an operator learns to distrust the refusal.
- PARTICIPATING¶
- EXCLUDED¶
- STORAGE_ROOT_SETTINGS_FIELD: Final[str]¶
The settings field naming the anchor every root-scoped member resolves against.
Neither a member nor an escape, and given its own name so it cannot be mistaken for either. It is not a member because the taxonomy declares locations relative to it – a member for the root would be a member whose subpath is itself. It is not an escape because the application both chooses it and writes beneath it. It is therefore the anchor rather than a member.
- class StorageCategory(*values)[source]¶
Bases:
StrEnumEvery application-chosen on-disk location, identified by scope and name.
Root-scoped members carry their bare category name. Bucket- and keystore-scoped members carry a scope-qualifying prefix, which is what keeps root-scoped names distinct from per-bucket subdirectories.
- TOKENS¶
- SECRETS¶
- BLOBS¶
- LIVE_STATE¶
- LIVE_STATE_IVA_WALLET¶
- LIVE_STATE_IVA_REMOTE_STATE¶
- LIVE_STATE_IVA_REMOTE_STATE_FILED_HISTORY¶
- LIVE_STATE_IVA_REMOTE_STATE_WALLET¶
- LOGS¶
- LOG_FILE¶
- LLM_USAGE¶
- LLM_RUN_TELEMETRY¶
- RUNS¶
- LLM_CACHE¶
- CORPUS_SEARCH_CACHE¶
- CORPUS_SEARCH_INDEX¶
- SUBMISSIONS¶
- SUBMISSIONS_AMENDMENT_RESULTS¶
- SUBMISSIONS_AMENDMENTS¶
- WORKFLOW_RUNS¶
- DRAFTS¶
- JUSTIFICANTES¶
- FILING_HISTORY¶
- FILED_DECLARATIONS¶
- IVA_COMPENSATION_HISTORY¶
- IVA_READ_EVIDENCE¶
- FINANCIAL_TRANSACTIONS¶
- INVOICES¶
- ATTACHMENTS¶
- ATTACHMENTS_MANIFESTS¶
- USAGE_RATIOS¶
- BUCKETS¶
- ACTIVE_PROFILE_POINTER¶
- ROOT_FALLBACK_DATABASE¶
- CONFIG_RESET_JOURNAL¶
- OPERATION_JOURNAL¶
- PROFILE_CUSTODY_TRANSACTION_JOURNAL¶
- PROFILE_CUSTODY_RECEIPT¶
- PROFILE_CUSTODY_HOLD_EVIDENCE¶
- PROFILE_CUSTODY_HOLD_LEGAL_OWNER¶
- PROFILE_CUSTODY_HOLD_FILING_OWNER¶
- PROFILE_CUSTODY_HOLD_DERIVED_EVIDENCE¶
- PROFILE_CUSTODY_LABEL_HEAD¶
- LOCAL_READER_FITNESS_VERDICTS¶
- BUCKET_DATABASE¶
- BUCKET_DATABASE_FILE¶
- BUCKET_BLOBS¶
- BUCKET_MANIFEST¶
- BUCKET_LOCK¶
- BUCKET_OUTPUT_LANGUAGE_HINT¶
- BUCKET_KEYSTORE¶
- PROFILE_CAPSULE_CUSTODY¶
- PROFILE_CAPSULE_PASSWORD_ENVELOPE¶
- PROFILE_CAPSULE_RECOVERY_ENVELOPE¶
- PROFILE_CAPSULE_DATA¶
- PROFILE_CAPSULE_COMMIT¶
- KEYSTORE_PROFILE_SESSION¶
- KEYSTORE_PROFILE_SESSION_RETIREMENT¶
- KEYSTORE_LOGIN_THROTTLE¶
- class StorageLocation(**data)[source]¶
Bases:
BaseModelOne declared location and every axis a bare name cannot carry.
Frozen and strict: the taxonomy is a declaration, and a mutable one would let a consumer rewrite the authority it is reading.
- Parameters:
category (StorageCategory)
subpath (str)
node_kind (StorageNodeKind)
scope (StorageScope)
override_policy (StorageOverridePolicy)
lifecycle (StorageLifecycle)
grouping (StorageGrouping)
fingerprint_participation (FingerprintParticipation)
settings_field (str | None)
derives_settings_default (bool)
consumer_module (str | None)
dormant_reason (str | None)
- category: StorageCategory¶
- subpath: str¶
POSIX-style path relative to this member’s scope anchor, verbatim.
- node_kind: StorageNodeKind¶
- scope: StorageScope¶
- override_policy: StorageOverridePolicy¶
- lifecycle: StorageLifecycle¶
- grouping: StorageGrouping¶
- fingerprint_participation: FingerprintParticipation¶
- settings_field: str | None¶
Flat
Settingsattribute holding the resolved path.Members name their settings field rather than absorbing it. Path fields stay flat, introspectable attributes on the settings model because the structural gates discover their subject by walking
Settings.model_fields; a model that hid them behind a nested object or a property would leave those gates discovering nothing, which passes silently and covers nothing.
- derives_settings_default: bool¶
Whether settings validation computes this field’s default from the root.
False for a member whose field is a deliberate opt-in override. The registry disk cache is the worked case: its name is governed here, but its field must stay absent by default because its resolver selects a shared temporary location under pytest precisely by observing that the field is unset. Governing the name and deriving the field are separate decisions.
- consumer_module: str | None¶
Production module that consumes this location, relative to
src/cadrumo.Names the module, and a structural gate verifies the claim: that module must contain a real reference to this member – an attribute load of the bound settings field, an attribute load of the category member, or the field name as a non-docstring string constant, which is how the live-evidence roots are reached. A name appearing in prose satisfies nothing.
The claim is deliberately consumption rather than write-reachability. Tracing statically from an attribute to a filesystem write produces a false negative on every indirection, and a gate that blocks legitimate changes is a gate somebody switches off. Consumption is weaker in theory and far stronger in practice, because a location no module touches cannot be written to – which is the condition worth catching.
Exactly one of this and
dormant_reasonis set.
- dormant_reason: str | None¶
Why this member has no consuming module, when it has none.
A declared location nothing reads or writes is a decision waiting to be taken – wire it or delete it – and the point of requiring the reason is that the decision becomes visible in the declaration instead of waiting to be rediscovered by an audit. Exactly one of this and
consumer_moduleis set.