Source code for cadrumo.application.operator_output.sandbox_notice
"""Sandbox-active indicator shared by every operator-facing JSON/text emitter.Any command surface that renders a success envelope or text line for theoperator — the CLI transport (:mod:`entrypoints.cli.common`) and the setupwizard (:mod:`application.wizard.commands`) alike — must be able to warn theoperator that the active profile bucket is a discardable sandbox rather thantheir real profile. Both surfaces need the SAME check, so it lives here,below both of them, rather than duplicated per surface.This module resolves the active label through the committed-capsule projectionrather than reading a mutable manifest. It stays cheap enough to call on everyemitted line, including the default text-mode path every terminal invocationtakes."""from__future__importannotationsfrom...core.json_contractimportNotice
[docs]defsandbox_notice_for_active_bucket()->Notice|None:"""Return the persistent sandbox-active :class:`Notice`, or ``None``. Resolves the active bucket id through the same core precedence chain every command uses (:func:`~cadrumo.core.bucket_pointer.resolve_active_bucket_id`), then reads its committed label projection and checks it against the reserved sandbox label prefix (:data:`~cadrumo.core.external_constants.SANDBOX_LABEL_PREFIX`). Returns ``None`` when no profile is active, the active bucket has no recognized committed capsule, or the active profile is not a sandbox, so a real profile's output is never annotated. The projection is deliberately re-read on every call (no caching) so a mid-process ``switch`` is reflected on the very next command. It reads the summary inventory rather than the authenticated aggregate. The aggregate takes a per-profile custody lock and can publish a label head as a side effect; paying that on every emitted line contradicted this module's own cheapness contract, and neither the lock nor the publication tells us anything a label check needs. """from...application.user_profile.profile_summaryimportsummary_inventoryfrom...core.bucket_pointerimportresolve_active_bucket_idfrom...core.config_state_rootimportFormerProductStateErrorfrom...core.external_constantsimportSANDBOX_LABEL_PREFIXfrom...core.i18n.renderimporttrfrom...core.json_contractimportNoticeSeveritytry:bucket_id=resolve_active_bucket_id()ifbucket_idisNone:returnNonelabel=next((item.labelforiteminsummary_inventory().summariesifitem.profile_id==bucket_id),None,)except(FormerProductStateError,ValueError):returnNoneiflabelisNone:returnNoneifnotlabel.startswith(SANDBOX_LABEL_PREFIX):returnNonereturnNotice(severity=NoticeSeverity.INFO,code="config.profile.sandbox.active_indicator",message=tr("cli.config.profile.sandbox.active_indicator_info",label=label,),)
[docs]defsandbox_banner_line(notice:Notice)->str:r"""Render ``notice`` as the tab-delimited text-mode ``SANDBOX`` banner line. Shared formatting so every text-mode emitter (CLI transport, wizard) prepends an identical banner rather than each hand-formatting its own ``"SANDBOX\t..."`` string. """returnf"SANDBOX\t{notice.message}"