Close INFD-IN-0001; design the independent evidence path; track both blockers
Housekeeping the ruling left behind, plus the one piece of blocked work that was substantially ours to move. INFD-IN-0001 closed with its resolution recorded, matching approval-engine's IN-0002 form. It was still open after GH-DEC-2026-012 answered it. INFD-IN-0003 and docs/evidence-path-design.md take up O-02, which was sitting in the blueprint as "mechanism unchosen". Read independence and the local transactional outbox are settled and not in question. The real question is what travels, and it is sharper for us than for approval-engine because a presentation record carries the brief and packet material actually shown to a human. Three candidates with costs; proposal is commitment-only for Stage 1 — hashes, principal, timestamps, acks, co-referenced approval id — which discharges limit 3 and removes our ability to alter the record, while leaving us able to erase the content. That residual is declared alongside the existing compromised-surface one rather than papered over. Deliberately not proposing the full binding document unilaterally: it would put commercial and personal material into the audit fabric under retention and export entitlements designed for audit events. That is a meaningful change in what audit-core holds and is its owner's to accept, not ours to assume. The third option, a separate evidence store, is refused here because that store has no owner and inventing one routes around the §16 decision against stronger archival custody. Cadence declared and its form argued rather than copied: approval-engine's heartbeat answer suits genuinely low-volume classes, but ours are mixed — presentations are one per render, while dispositions and stance applications are low-volume and are the security-relevant ones. Reconciliation per class as primary, heartbeat for the low-volume classes. Depends on AUDIT-WP-0009 T04/T06; declared, not claimed operating. INFD-IN-0002 files the tenant blocker as a tracked record rather than leaving it in message threads and a blueprint footnote. T07 and T08 now name their blocking intakes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR Assistant: claude-code Assistant-Model: opus Assistant-Process: 1565372@bnt-lap001 Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
This commit is contained in:
parent
d50f480075
commit
024946e9da
5 changed files with 336 additions and 9 deletions
|
|
@ -13,8 +13,8 @@
|
|||
| task | INFD-WP-0001-T02 | done | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T03 | done | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T04 | done | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T05 | todo | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T06 | progress | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T05 | done | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T06 | done | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T07 | todo | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| task | INFD-WP-0001-T08 | todo | — | workplans/INFD-WP-0001-founding-specs-and-approver-ui-ownership.md |
|
||||
| intake | INFD-IN-0001 | open | blue | intakes/intakes.md |
|
||||
|
|
|
|||
184
docs/evidence-path-design.md
Normal file
184
docs/evidence-path-design.md
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
# The independent evidence path — design and decision request
|
||||
|
||||
**From:** informed-decision
|
||||
**Raised:** 2026-09-09
|
||||
**Intake:** `INFD-IN-0003`
|
||||
**Blocks:** `INFD-WP-0001-T08`
|
||||
**Governing:** `GH-DEC-2026-012` limit **L3-independent-evidence-path**
|
||||
**Addressed to:** `audit-core` (registration and payload), `gate-house` (the
|
||||
content question, if it is doctrine)
|
||||
|
||||
---
|
||||
|
||||
## 1. The obligation
|
||||
|
||||
`GH-DEC-2026-012` permitted this repository to emit a presentation claim under
|
||||
three limits. The third:
|
||||
|
||||
> The evidence copy reaches `audit-core` **independently** of you. Claim
|
||||
> endpoint and evidence path are different things and neither substitutes for
|
||||
> the other. […] audit evidence is protected from the actor being audited, and
|
||||
> here the actor and the source are the same component. The copy that is
|
||||
> evidence must not be reachable only through the party it is evidence about.
|
||||
|
||||
Gate House named this the limit that matters most in our case, and we agree: we
|
||||
render the view, we compute the hash over it, and we are the party an auditor is
|
||||
checking. A design where the only route to the evidence runs through us is not
|
||||
evidence.
|
||||
|
||||
`docs/specs/ArchitectureBlueprint.md` `O-02` records the mechanism as unchosen
|
||||
and states T08 must not ship without it, because "we will add the independent
|
||||
path later" is how limit 3 becomes limit-3-in-principle.
|
||||
|
||||
## 2. What is settled and not being asked
|
||||
|
||||
**Read independence is the property.** A reader obtains the evidence from
|
||||
`audit-core` without asking us and without our cooperation. Our claim endpoint
|
||||
serves presentation claims to consumers; it is a different surface with a
|
||||
different purpose and does not discharge this obligation.
|
||||
|
||||
**The write path is a local transactional outbox.** Adopted from
|
||||
`approval-engine`'s reasoning rather than rediscovered: the queue lives in our
|
||||
own store, written in the **same transaction** as the state change it evidences.
|
||||
Emit-after-commit is a defect. The queue is local so an `audit-core` outage
|
||||
cannot block a binding act, for the same reason it must not block a revocation
|
||||
upstream.
|
||||
|
||||
**Atomicity covers accident, not compromise.** It does not close the residual in
|
||||
`layer.yaml` and will not be described as doing so.
|
||||
|
||||
**Cadence is owed.** Our `layer.yaml` declares presentation evidence
|
||||
**load-bearing**, so §9.6 requires a declared cadence. See §5.
|
||||
|
||||
## 3. The question: what travels
|
||||
|
||||
A presentation record is not like an approval transition. It contains, or points
|
||||
at, the **brief and packet material actually shown to a human** — which is
|
||||
frequently commercially or personally sensitive. So "emit the evidence" is
|
||||
ambiguous in a way it was not for `approval-engine`, and the ambiguity has to be
|
||||
resolved before we build, not after we have shipped a payload shape.
|
||||
|
||||
Three candidates.
|
||||
|
||||
### (a) Commitment only — hash and metadata
|
||||
|
||||
Emit `memo_id`, `memo_version`, `presentation_id`, `principal`, `locale`,
|
||||
`ui_release`, `rendered_at`, `acked_highlight_ids`, `view_hash`,
|
||||
`awareness_hash`, the co-referenced approval identifier, the disposition verb,
|
||||
and the stance application. **Not** the brief, not the packet, not the highlight
|
||||
text.
|
||||
|
||||
- **Proves independently:** that this principal was shown a view whose canonical
|
||||
form hashes to H, at time T, and bound act A against approval X.
|
||||
- **Cost:** the *content* lives only here. An auditor can verify that content we
|
||||
later produce matches H, and can detect alteration — but if we destroy it,
|
||||
nobody can ever see what was shown. Audit-core proves the commitment, not the
|
||||
material.
|
||||
- **Also:** this is strictly stronger than storing nothing, because it removes
|
||||
our ability to alter the record after the fact. It does not remove our ability
|
||||
to erase it.
|
||||
|
||||
### (b) Full binding document
|
||||
|
||||
Emit the canonical binding document itself, from which `view_hash` is
|
||||
recomputable.
|
||||
|
||||
- **Proves independently:** everything (a) does, plus what was actually shown,
|
||||
surviving our compromise or our deletion.
|
||||
- **Cost:** `audit-core` now holds business-sensitive and possibly personal
|
||||
content, under retention profiles and export entitlements designed for audit
|
||||
events rather than for the substance of commercial decisions. Its
|
||||
secret-finding and redaction surfaces would be operating on material where a
|
||||
redaction is not a defect-signal but routine. That is a meaningful change in
|
||||
what `audit-core` is holding, and it is theirs to accept or refuse — not ours
|
||||
to assume.
|
||||
- **Also:** an L4 instrument under (b) puts contract text in the audit fabric.
|
||||
|
||||
### (c) Split — commitment to `audit-core`, content to a separate evidence store
|
||||
|
||||
(a)'s payload to `audit-core`, plus the full bundle to a store that is neither
|
||||
`audit-core` nor us.
|
||||
|
||||
- **Proves independently:** as (b).
|
||||
- **Cost:** a store with no owner. There is no such component today, and
|
||||
inventing one to satisfy a limit is how a surface acquires an operational axis
|
||||
it was never given. §16 also decided against stronger archival custody for
|
||||
approval evidence, and we should not route around that decision by building a
|
||||
parallel archive under another name.
|
||||
|
||||
## 4. What we propose
|
||||
|
||||
**(a) for Stage 1, with the gap stated rather than papered over.**
|
||||
|
||||
Reasoning:
|
||||
|
||||
1. It discharges limit 3 as written. The copy that is evidence — the commitment
|
||||
that a presentation with hash H happened to principal P at time T — is
|
||||
reachable from `audit-core` without us.
|
||||
2. It does not silently expand what `audit-core` holds. Expanding that is a
|
||||
decision for its owner, and (b) presented as a fait accompli would be exactly
|
||||
the drift we asked gate-house to prevent in a different context.
|
||||
3. It is honest about what it does not close: **we can still erase the
|
||||
content.** That residual is adjacent to the one `layer.yaml` already declares
|
||||
(a compromised surface presents X and attests Y) and belongs in the same
|
||||
place — declared, tracked, not claimed as closed.
|
||||
4. (b) remains available and is a payload change, not a redesign, if the estate
|
||||
later decides a commitment is insufficient.
|
||||
|
||||
**We are not asking to defer (b) indefinitely.** We are asking whether the
|
||||
content question is `audit-core`'s to answer as its custodian, or `gate-house`'s
|
||||
as doctrine. If it is doctrine and the ruling is (b), we will implement (b).
|
||||
|
||||
## 5. Cadence
|
||||
|
||||
Presentation evidence is declared load-bearing, so §9.6 requires a cadence and
|
||||
rate monitoring is not automatically the right form.
|
||||
|
||||
Note a difference from `approval-engine`: their classes are genuinely low-volume
|
||||
(a handful of revocations a month), which is why heartbeat is their answer.
|
||||
Ours are mixed:
|
||||
|
||||
- **Presentations** are relatively high-volume — one per render.
|
||||
- **Dispositions and stance applications** are low-volume and are the
|
||||
security-relevant ones.
|
||||
|
||||
So we propose **reconciliation as the primary form**, per class: our own count
|
||||
of presentations, dispositions and stance applications compared against
|
||||
`audit-core`'s event count per class, with divergence a finding. Plus a
|
||||
**heartbeat for the low-volume classes**, because a quiet month of dispositions
|
||||
is indistinguishable from suppression by rate alone — the same argument
|
||||
`approval-engine` makes.
|
||||
|
||||
This depends on `AUDIT-WP-0009` T04/T06, which we understand are open. We are
|
||||
declaring the cadence now and will not describe it as operating until those
|
||||
land.
|
||||
|
||||
## 6. What we need
|
||||
|
||||
| From | Decision |
|
||||
| --- | --- |
|
||||
| `audit-core` | Sender registration for `informed-decision`, and whether payload (a) or (b) is acceptable to hold |
|
||||
| `audit-core` | Whether reconciliation-plus-heartbeat is the right cadence form for a mixed-volume source |
|
||||
| `gate-house` | Only if the content question is doctrine rather than custody |
|
||||
|
||||
Proposed registration, following `approval-engine`'s form:
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| Sender and permitted source | `informed-decision` (exact) |
|
||||
| Tenants | `["tenant:platform"]` — but see the open tenant question, `INFD-IN-0002` |
|
||||
| Write / read | `true` / `false` |
|
||||
| Evidence kind | `load-bearing` |
|
||||
| Cadence form | reconciliation, plus heartbeat for low-volume classes |
|
||||
| Secret policy | `redact` |
|
||||
|
||||
`redact` chosen for the same reason `approval-engine` chose it: a receiver
|
||||
should retain a legitimate record with an accidentally secret-shaped field
|
||||
removed rather than reject the event and leave delivery pending. Under payload
|
||||
(a) the exposure is small by construction; under (b) `redact` would be doing
|
||||
substantially more work, which is itself an argument for (a).
|
||||
|
||||
**Note the coupling:** the tenant on our registration is the same unresolved
|
||||
question as `INFD-IN-0002`. If a human token cannot carry `tenant:platform`, our
|
||||
audit registration tenant and our approval tenant should be settled together
|
||||
rather than separately.
|
||||
|
|
@ -131,10 +131,19 @@ Consequences, binding on implementation:
|
|||
4. **Atomicity covers accident, not compromise.** It does not close the residual
|
||||
in `layer.yaml`, and must never be described as doing so.
|
||||
|
||||
Open for implementation: whether the independent path is `audit-core` pull,
|
||||
a separately-credentialed push, or a third party drain. **T08 must not ship
|
||||
without one chosen**, because "we will add the independent path later" is how
|
||||
limit 3 quietly becomes limit 3-in-principle.
|
||||
**Cadence is owed**, because `layer.yaml` declares presentation evidence
|
||||
load-bearing (§9.6). The form differs from `approval-engine`'s: their classes are
|
||||
genuinely low-volume, so a heartbeat is the answer. Ours are mixed —
|
||||
presentations are high-volume (one per render), while dispositions and stance
|
||||
applications are low-volume and are the security-relevant ones. Proposed:
|
||||
reconciliation per class as the primary form, plus a heartbeat for the
|
||||
low-volume classes, since a quiet month of dispositions is indistinguishable
|
||||
from suppression by rate alone. Depends on `AUDIT-WP-0009` T04/T06; declared,
|
||||
not claimed operating.
|
||||
|
||||
What travels is the open question — see `docs/evidence-path-design.md` and O-02.
|
||||
**T08 must not ship without it chosen**, because "we will add the independent
|
||||
path later" is how limit 3 quietly becomes limit 3-in-principle.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -236,8 +245,15 @@ condition that it holds *only* because registrations are static and
|
|||
deployment-owned should be written into the contract, not left as reasoning in a
|
||||
message.
|
||||
|
||||
**O-02 — The independent evidence path.** Its mechanism is unchosen. Must be
|
||||
resolved before T08 ships.
|
||||
**O-02 — The independent evidence path.** Design and decision request written:
|
||||
`docs/evidence-path-design.md`, filed as `INFD-IN-0003`. Read independence and
|
||||
the local transactional outbox are settled; the open question is **what
|
||||
travels**, because a presentation record carries the brief and packet material
|
||||
actually shown to a human. Proposal is commitment-only (hashes, principal,
|
||||
timestamps, acks, co-referenced approval id) for Stage 1, with the erasure
|
||||
residual declared rather than papered over. Awaiting `audit-core` on the payload
|
||||
and the sender registration, and `gate-house` only if the content question is
|
||||
doctrine. Must be resolved before T08 ships.
|
||||
|
||||
**O-03 — Requester identity for an engine-originated memo.** `approval-engine`
|
||||
does not model a requester. Likely the approval's `principal`; needs confirming
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
id: INFD-IN-0001
|
||||
kind: intake
|
||||
title: Layer placement and approver-UI ownership
|
||||
status: open
|
||||
status: closed
|
||||
origin: coordination
|
||||
origin_ref: INFD-WP-0001-T02
|
||||
priority: high
|
||||
|
|
@ -18,6 +18,23 @@ tags:
|
|||
- cross-repo
|
||||
created: '2026-09-09'
|
||||
updated: '2026-09-09'
|
||||
resolution: >-
|
||||
Resolved 2026-09-09 as GH-DEC-2026-012 (gate-house@0a1d1d9), within a day of
|
||||
filing. All three ruled. R1: PEP-shaped, confirmed as proposed; the ruling
|
||||
settles the shape, the layer stays this repository's to declare, so layer.yaml
|
||||
is written in its own voice. R2: yes to a presentation claim and no second
|
||||
catalog row — PEP and PIP are shapes a repository has — under three limits now
|
||||
declared and tested in layer.yaml; limit 2 (never an input to the decision it
|
||||
presents for) is load-bearing, since the self-dealing argument was accepted
|
||||
because it holds. R3: option (b) as proposed, with the authority rule written
|
||||
down — the binding digest is authoritative for what the request is, view_hash
|
||||
only for what was shown, neither substitutable, and a disagreement between
|
||||
them is a finding against the presenting surface rather than a fact about the
|
||||
request. Linkage is co-reference; (c) was refused because nesting reproduces
|
||||
the GH-DEC-2026-008 hash cycle. Also directed: build the stance map to v0.8
|
||||
obligation 3 rather than migrate later, and inherit GH-DEC-2026-010 as a
|
||||
declared open gap. Delivered in layer.yaml, pep-stance.yaml,
|
||||
informed_decision/stance.py and tests/test_layer_conformance.py.
|
||||
description: >-
|
||||
approval-engine names an approvals inbox under Non-Goals, leaving the
|
||||
browser-facing approver UI unowned; key-cape KEY-WP-0013-T02 is blocked on a
|
||||
|
|
@ -38,3 +55,98 @@ description: >-
|
|||
Blocks INFD-WP-0001 T05 and T07; T03, T04 and T06 proceed regardless.
|
||||
state_hub_intake_id: "01a08610-f458-7fd5-b284-26a65d1d73c2"
|
||||
```
|
||||
|
||||
## INFD-IN-0002 — Human access tokens cannot carry `tenant:platform`
|
||||
|
||||
```yaml
|
||||
id: INFD-IN-0002
|
||||
kind: intake
|
||||
title: Human access tokens cannot carry tenant:platform
|
||||
status: open
|
||||
origin: coordination
|
||||
origin_ref: INFD-WP-0001-T07
|
||||
priority: high
|
||||
owner: key-cape
|
||||
repo: informed-decision
|
||||
lane: blue
|
||||
tags:
|
||||
- decision-request
|
||||
- cross-repo
|
||||
- blocker
|
||||
created: '2026-09-09'
|
||||
updated: '2026-09-09'
|
||||
description: >-
|
||||
Raised by key-cape (KEY-WP-0013-T05) while reviewing the approver client
|
||||
shape, and it blocks INFD-WP-0001-T07. The tenant claim on a human token
|
||||
resolves from the directory user record via effectiveTenant(user); no adapter
|
||||
populates domain.User.Tenant, so every human token falls back to the platform
|
||||
default tenant:coulomb. The per-client tenant field, which is how the two
|
||||
approval service clients carry tenant:platform, is read only on the
|
||||
client_credentials path. approval-engine compares tenant by exact string
|
||||
equality and pins near-miss spellings as refused, so an approver token issued
|
||||
today would be rejected and the failure would surface as a rejected approval
|
||||
rather than as a registration defect. Two resolutions: directory-sourced
|
||||
(tenant becomes a property of the person and changes everywhere, needs a
|
||||
directory attribute and an owner for who is a platform-zone human), or
|
||||
registration-bound and fail-closed (symmetric with the service registrations
|
||||
and with decision 5ed3fb35, but writes a cross-tenant capability into the
|
||||
issuer). informed-decision prefers registration-bound: under it the tenant is
|
||||
a property of the surface and its registration, which is exactly what the
|
||||
pre-sign binding slice commits, whereas directory-sourced makes tenant
|
||||
describe the person, which is closer to awareness than to binding. key-cape
|
||||
leans the same way but will not implement either unilaterally. Not this
|
||||
repository's to decide alone; routed to key-cape, approval-engine and
|
||||
gate-house. If registration-bound is chosen, the condition that it holds only
|
||||
because registrations are static and deployment-owned should be written into
|
||||
the contract rather than left as reasoning in a message. Blocks T07; the
|
||||
client_id and callback URI will not be published until it is resolved, since
|
||||
registering a client that fails closed at first use is the failure key-cape
|
||||
flagged.
|
||||
```
|
||||
|
||||
## INFD-IN-0003 — The independent evidence path: what travels to audit-core
|
||||
|
||||
```yaml
|
||||
id: INFD-IN-0003
|
||||
kind: intake
|
||||
title: The independent evidence path — what travels to audit-core
|
||||
status: open
|
||||
origin: residual
|
||||
origin_ref: INFD-WP-0001-T05
|
||||
priority: high
|
||||
owner: audit-core
|
||||
repo: informed-decision
|
||||
lane: blue
|
||||
tags:
|
||||
- decision-request
|
||||
- cross-repo
|
||||
created: '2026-09-09'
|
||||
updated: '2026-09-09'
|
||||
description: >-
|
||||
GH-DEC-2026-012 limit L3 requires the evidence copy to reach audit-core
|
||||
independently of informed-decision, because here the actor being audited and
|
||||
the evidence source are the same component. Read independence and a local
|
||||
transactional outbox are settled and not in question. The open question is
|
||||
what travels, and it is sharper here than for approval-engine because a
|
||||
presentation record contains the brief and packet material actually shown to a
|
||||
human, which is frequently commercially or personally sensitive. Three
|
||||
candidates with costs are in docs/evidence-path-design.md: (a) commitment only
|
||||
— hashes, principal, timestamps, acks, co-referenced approval id — which
|
||||
discharges limit 3 and removes our ability to alter the record but not to
|
||||
erase the content; (b) the full binding document, which survives our
|
||||
compromise but puts commercial and personal material into the audit fabric
|
||||
under retention and export entitlements designed for audit events, a
|
||||
meaningful change in what audit-core holds and its owner's to accept or
|
||||
refuse; (c) a split with a separate evidence store, refused here because that
|
||||
store has no owner and inventing one routes around the §16 decision against
|
||||
stronger archival custody. informed-decision proposes (a) for Stage 1 with the
|
||||
erasure residual declared alongside the existing compromised-surface residual,
|
||||
and asks whether the content question is audit-core's as custodian or
|
||||
gate-house's as doctrine. Also requests a sender registration and asks whether
|
||||
reconciliation plus a heartbeat for low-volume classes is the right cadence
|
||||
form for a mixed-volume source — presentations are high-volume, dispositions
|
||||
and stance applications are low-volume and are the security-relevant ones.
|
||||
Cadence depends on AUDIT-WP-0009 T04/T06 and is declared, not claimed
|
||||
operating. The registration tenant is coupled to INFD-IN-0002. Blocks
|
||||
INFD-WP-0001-T08.
|
||||
```
|
||||
|
|
|
|||
|
|
@ -352,6 +352,16 @@ registration is accepted by `approval-engine`'s verifier; `KEY-WP-0013-T02` is
|
|||
unblocked. **This is the task that discharges the gap that created this
|
||||
repository.**
|
||||
|
||||
2026-09-09: blocked on `INFD-IN-0002`. `key-cape` found that a human access
|
||||
token cannot carry `tenant:platform` today — the tenant claim resolves from a
|
||||
directory record no adapter populates, so every human token falls back to
|
||||
`tenant:coulomb`, which `approval-engine` refuses by exact match. Registering
|
||||
the client before this is resolved would ship a login that fails closed at first
|
||||
use, and the failure would present as a rejected approval rather than as a
|
||||
registration defect. Position stated (registration-bound) with an
|
||||
evidence-model reason, and routed — it writes a cross-tenant capability into the
|
||||
issuer, so it is not this repository's to decide alone.
|
||||
|
||||
## Walking skeleton — one approval, end to end
|
||||
|
||||
```task
|
||||
|
|
@ -380,6 +390,11 @@ act is permitted.
|
|||
Gated externally on `approval-engine` `APPROVAL-WP-0002-T01` reaching `done` and
|
||||
on the service being deployed with an origin this surface can reach.
|
||||
|
||||
2026-09-09: additionally gated on `INFD-IN-0003` — `GH-DEC-2026-012` limit 3
|
||||
requires the evidence copy to reach `audit-core` independently of this
|
||||
component, and the payload question is open. Design and decision request in
|
||||
`docs/evidence-path-design.md`. This task must not ship before it is answered.
|
||||
|
||||
## Known risks
|
||||
|
||||
- **T02 is a hard gate.** Writing the blueprint before the layer ruling risks
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue