cadrumo.application.user_profile.profile_summary module¶
The pure, non-authenticating profile listing boundary.
This module is the whole public surface for “which profiles exist and what are
they called”. It is deliberately separate from
cadrumo.application.user_profile.profile_repository: that module owns the
authenticated aggregate, and reaching it pulls the transaction journal, the
password material reader, and the label-head publisher – roughly a hundred
modules, and a per-profile custody lock, to answer a question that needs
neither.
Listing therefore never unwraps a DEK, derives a key, reads keyring or session state, opens a password or recovery envelope, authenticates a sentinel, reads encrypted facts, runs recovery, publishes a label head, or repairs a projection. Those all remain with the commands that own them.
- class ProfileSummary(**data)[source]¶
Bases:
BaseModelListing projection with no key, KDF, manifest, or recovery material.
Every field is read from the two records one anchored observation already proved coherent, so building a summary costs no further filesystem work and cannot carry another capsule’s provenance. There is deliberately nothing here that implies custody health: a summary says a capsule is committed and what it is called, never that it can be unlocked.
- Parameters:
profile_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=36, pattern=^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$, ascii_only=None)])
label (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=160, pattern=None, ascii_only=None), AfterValidator(func=~cadrumo.core.identity.profile_label._reject_uuid_shaped_label)])
label_revision (int)
published_at (datetime)
publication_kind (Literal[ProfilePublicationKind.ENROLL, ProfilePublicationKind.RESTORE])
- profile_id: ProfileId¶
- label: ProfileLabel¶
- label_revision: int¶
- published_at: datetime¶
- publication_kind: ProfilePublicationKindValue¶
- class ProfileSummaryInventory(**data)[source]¶
Bases:
BaseModelThe complete result of one non-authenticating listing observation.
A caller reads
outcomebeforesummaries. A degraded or concurrent observation carries no summaries at all rather than a partial set, because a partial listing is indistinguishable from a store that genuinely holds fewer profiles – and “your profile is gone” is the one wrong answer this boundary must never give.- Parameters:
outcome (ProfileSummaryOutcome)
summaries (tuple[ProfileSummary, ...])
detail (str | None)
- outcome: ProfileSummaryOutcome¶
- summaries: tuple[ProfileSummary, ...]¶
- detail: str | None¶
- summary_inventory_snapshot()[source]¶
Let everything inside one read-only command share one listing observation.
A single command asks which profiles exist from several layers – the session gate, the active-bucket resolver, the envelope’s profile label, the sandbox notice – and each paid a full anchored scan. Inside this scope the first recognized observation of a root answers the rest. The scope is the whole cache: nothing survives it, because the store belongs to other processes too, and a command that writes profile state must not open one. Nested scopes share the outermost observation.
- summary_inventory(*, root=None)[source]¶
Project every committed capsule from recognized witnesses alone.
The adapter’s single anchored scan is the entire read: an empty store costs one directory enumeration, and a populated one costs two bounded reads per profile. Both failure endings are typed rather than raised, because a listing that cannot be trusted must still render – saying so – instead of aborting the command an operator ran to find out what they have.
Within
summary_inventory_snapshot()a recognized observation is reused for the same root; a degraded or concurrent one never is, so a retry inside the command observes the store again.- Return type:
- Parameters:
root (Path | None)
- require_summaries(*, root=None)[source]¶
Return the summaries, refusing rather than reporting a degraded read.
summary_inventory()reports an unreadable store as a typed outcome with no rows, which is right for a surface that can show the operator why. A caller that only gets a sequence back cannot show anything, and an empty sequence there would mean “you have no profiles” – the opposite of the truth, and the answer that makes someone think their data is gone. Such a caller uses this instead and handles the refusal.- Return type:
- Parameters:
root (Path | None)