"""Unified access gate for live AEAT reads and permanent write refusal.The gate consolidates live-test preconditions for pytest-driven livereads while keeping operator-facing live reads as operational surfaces.Live AEAT writes are permanently forbidden, so the write-side helperalways raises a typed refusal. The gate is consumed by the repair CLIfor surfacing a "Live access gate" row and by every live-read module(filing history, missing-filing detection, AEAT messages, IVA balancetracking) that needs a typed precondition rather than per-call-site``if os.environ[...] != "1"`` boilerplate in tests.The gate is always constructed inline from a:class:`core.config.Settings` instance at the call site. It isnever injected via a constructor, never stored as state on engines,and never passed as a kwarg that could make a write pathsubstitutable. That anti-injection stance preserves the"no substitutable dependency on the write-gate" property: testscannot swap the gate for a no-op because there is no seam to swapthrough.See Also: :class:`AeatAccessGate` Inline gate object used by read-only live surfaces and permanent write-refusal checks. :mod:`application.live` Read-only application-live facade that calls the read gate before opening AEAT remote surfaces."""from__future__importannotationsfromdataclassesimportdataclassfromtypingimportTYPE_CHECKINGfrom..config_live_testsimportLIVE_READ_TEST_OPT_IN_ENV_VARas_LIVE_READ_TEST_OPT_IN_ENV_VARfrom.errorsimport(AeatLiveReadNotEnabledError,LiveSubmitForbiddenError,)ifTYPE_CHECKING:from..configimportSettings
[docs]@dataclass(frozen=True,slots=True)classAeatAccessGate:"""Pre-flight gate that authorises live AEAT reads and writes. The gate is stateless with respect to the process; every call reads ``os.environ`` afresh so the result reflects the live shell state at the moment of the check. That behaviour matches the engine's inline checks by design: a test that sets an env var at module import but unsets it before the gate call gets the expected "not enabled" verdict. """settings:Settings
[docs]deflive_read_requires_test_opt_in(self,*,guarded_read_context:str|None=None)->bool:"""Return whether the caller explicitly requested the guarded-read path. ``CADRUMO_LIVE_TESTS_ENABLED`` is a test runner opt-in, not an operational CLI switch. A live read in a normal operator shell still passes through auth/profile/read-only guards, but it is not refused by the pytest-only environment variable. """returnbool(guarded_read_context)
[docs]defrequire_live_read(self,*,guarded_read_context:str|None=None)->None:"""Refuse pytest-driven live AEAT reads unless the test opt-in is on. Routes the check through :class:`core.config.Settings` (specifically the ``cadrumo_live_tests_enabled`` field) so every config read in the codebase flows through a single validated surface. Outside pytest this method deliberately permits the read to continue to the operational auth/profile and read-only remote-state guards. Raises: AeatLiveReadNotEnabledError: During pytest execution, when ``Settings.cadrumo_live_tests_enabled`` is not ``"1"``. """ifself.live_read_requires_test_opt_in(guarded_read_context=guarded_read_context)and(notself.settings.live_tests_enabled):raiseAeatLiveReadNotEnabledError(translated_message="errors.refused.refused_access_gate_live_read_not_enabled",context={"env_var":_LIVE_READ_TEST_OPT_IN_ENV_VAR,"required_value":"1","current_value":str(self.settings.cadrumo_live_tests_enabled),"live_reads_enabled":False,},)
[docs]defrequire_live_write(self)->None:"""Always refuse live AEAT writes. Live AEAT submission is permanently forbidden. This method exists so that any call-site attempting a write receives a typed, auditable refusal rather than a silent no-op. Raises: LiveSubmitForbiddenError: Always — live writes are permanently forbidden. """raiseLiveSubmitForbiddenError()