# EcoKure Pty Ltd — Security Posture Pack

**Version 1.0 · EcoKure Pty Ltd (ACN 699 693 779) · last reviewed 2026-08-19 · next review 2027-02-19**
**Owner: Director, EcoKure Pty Ltd**

> This document is generated from `docs/security/security_posture.yaml`. Edit the YAML, not this file, and rebuild with `python scripts/build_security_pack.py`. The build fails if any control claims a status it cannot evidence.

## How to read this

Every answer below carries a status, and no answer is marked IMPLEMENTED unless a repository artefact, an automated test, or an executed procedure supports it. Where a control is not in place it says so. EcoKure is a pre-revenue company with one director, and several controls a larger vendor would have are marked PLANNED rather than dressed up. A reviewer should treat the gaps section as the most useful part of this document.

It is structured to answer the questions a SIG Lite or CAIQ style assessment asks, without reproducing any proprietary questionnaire. No alignment or certification is claimed against either framework.

| Status | Meaning | Count |
|---|---|---|
| `IMPLEMENTED` | In place today, with evidence in this repository or an executed procedure. | 28 |
| `PARTIALLY_IMPLEMENTED` | In place for some deployments or some of the control's scope. | 16 |
| `CUSTOMER_CONFIGURED` | The customer owns this in their environment; we document the boundary. | 3 |
| `PLANNED` | Not in place. Named here so it is not mistaken for a control. | 8 |
| `NOT_APPLICABLE` | Does not apply to how this product works. | 0 |

**55 controls.** Every `IMPLEMENTED` and `PARTIALLY_IMPLEMENTED` answer cites a repository artefact, an automated test or an executed procedure, and every cited path is checked to exist when this document is built.

## What is not in place

Listed first deliberately. A reviewer's time is better spent here.

- **KEY-06 · Signing key custody** — No. Keys are software keys held by the service. There is no HSM and no claim of one. A provider interface exists so that AWS KMS, Azure Key Vault, Google Cloud KMS or a PKCS#11 HSM can be added without changing what an evidence pack means, because packs reference a key identifier rather than key material. No such provider is configured today, and the status command reports hardware_backed as false.
- **KEY-07 · Signing key custody** — No. EcoKure has one director, who requests, approves and performs every custody operation. This is a genuine gap and is recorded as one. The compensating control is that every operation writes an immutable audit event naming the actor, and the trail can be given to a customer for independent review.
- **IAM-02 · Identity and access control** — Not for the API, which is machine to machine and uses keys. SAML or OIDC for the administrative interface is not built.
- **IAM-04 · Access review** — No formal review cycle exists. With one administrator there is nothing to review today, but this will not remain true and it is not presented as a control.
- **LOG-03 · Monitoring** — Application logs and platform health checks exist. There is no security information and event management system, no alerting on anomalous authentication, and no on-call rotation.
- **BCP-03 · Disaster recovery objectives** — No RTO or RPO is committed. Publishing a number that has never been tested would be worse than saying this.
- **ASR-01 · Independent assurance** — No penetration test has been performed and no independent security assurance engagement has been completed. An external engineer conducted an architecture and code audit of the DTL system, which is useful but is neither of those things, and it did not cover concurrency or load. Concurrency was subsequently tested by us, which found and fixed real defects, and that is our own testing, not third party validation.
- **CRT-01 · Certifications** — None. EcoKure holds no SOC 2 report, no ISO 27001 certification, no HIPAA attestation and no FedRAMP authorisation, and is not in an active certification process for any of them. A customer requiring certified vendors should treat this as disqualifying rather than as a roadmap item.

## Controls

### Company and product

#### `ORG-01` · What does the product do, and what is the vendor's size and maturity?

**IMPLEMENTED**

EcoKure supplies deterministic verification gates. A gate takes a proposed output or action and returns an allow or refuse decision with a machine checkable certificate. The company is pre-revenue with one director. Nothing in this pack should be read as describing a large security organisation.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`, `README.md`*

#### `ORG-02` · Is the vendor's public claim set narrower than its evidence?

**IMPLEMENTED**

Internal benchmarks are never described as independent validation. Benchmark procedure requires that a result counts only when the unmodified harness is the authority and an integrity scan is clean, and where an earlier internal result failed that bar the finding was written down rather than removed. A reviewer should read the honest-loop handoffs cited here as the record of what was rejected, not only of what was kept.

*Evidence: `docs/PROGRAMBENCH_HONEST_LOOP_HANDOFF.md`, `docs/TERMINALBENCH_HONEST_LOOP_HANDOFF.md`*

### Deployment models

#### `DEP-01` · Can the product run fully offline or air-gapped?

**IMPLEMENTED**

Yes. The gates are deterministic and local, the keystore is a directory on disk, and the attestation chain is a local SQLite database. A test asserts that the entire key custody lifecycle completes with all socket connections blocked, so a dependency on a network call would fail CI rather than surprise an air-gapped customer.

*Evidence: `tests/fast/test_keyring.py`, `modules/dtl_registry/keyring.py`*

#### `DEP-02` · What deployment models are supported?

**PARTIALLY_IMPLEMENTED**

Offline, on-premises and private cloud are supported by the same container and require no outbound connectivity. Public multi-tenant SaaS is what EcoKure operates today. On-premises has been engineered for but has not yet been installed by a customer, so it is proven by design and tests rather than by an operating reference installation.

*Evidence: `Dockerfile.web`, `railway.toml`*

### Shared responsibility

#### `DEP-03` · Where does the vendor's responsibility end?

**IMPLEMENTED**

SaaS: EcoKure operates the application, the keystore, the attestation chain and the hosting configuration. The customer owns their API key handling, who they grant access to, and their retention of issued evidence packs. On-premises: the customer owns the host, the operating system, backups, network controls, database encryption and physical security. EcoKure supplies the software, the custody procedures and the verification tooling.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`*

### Architecture and trust boundaries

#### `ARCH-01` · What are the trust boundaries?

**IMPLEMENTED**

Three. Signing authority never leaves the host and no interface returns private key material. Verification material is published freely, because a public key is what lets a customer check our work without being able to forge it. The customer side holds evidence packs, which reference a key identifier and never key material, and can be verified with no connection back to us.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`, `modules/dtl_registry/keyring.py`*

#### `ARCH-02` · Is verification possible without trusting the vendor at run time?

**IMPLEMENTED**

Yes, and this is the central design property. Every verdict is appended to a hash chain whose head is signed, and any holder of a pack plus the published public key can recompute the chain and check the signature offline.

*Evidence: `modules/dtl_registry/attestation.py`, `tests/fast/test_apigate_attestation.py`*

### Data categories

#### `DATA-01` · What customer data is collected?

**IMPLEMENTED**

The content submitted for verification, for the duration of the call; the resulting verdict; and usage counters. Tenant and entitlement records hold an organisation name, a plan and counters.

*Evidence: `modules/dtl_registry/entitlements.py`, `PRIVACY.md`*

#### `DATA-02` · What is explicitly not collected?

**IMPLEMENTED**

The transparency chain does not store the content of a verification, or even a recomputable hash of it. It stores a hiding commitment over the certificate hash with a 128 bit nonce, because the gates are open source and a raw hash over a low entropy input, a drug and a dose and a weight for instance, would be brute forceable by anyone reading the public log.

*Evidence: `modules/dtl_registry/attestation.py`, `tests/fast/test_apigate_attestation.py`*

### Data flow and storage

#### `DATA-03` · Where does data go and where is it stored?

**IMPLEMENTED**

Submitted content is processed in memory and is not persisted by the gate. Persisted state is the attestation chain, tenant and entitlement records, and the keystore. In a customer-hosted deployment none of this leaves their infrastructure.

*Evidence: `modules/dtl_registry/attestation.py`, `modules/dtl_registry/entitlements.py`*

### Tenancy and segregation

#### `TEN-01` · How are tenants isolated?

**IMPLEMENTED**

A tenant is a first class object. Entitlements belong to a tenant and API keys are bound to both, so rotating a credential does not disturb a subscription. Cross-tenant isolation is asserted by test and exercised under concurrency by a harness that runs the metering path across multiple processes.

*Evidence: `modules/dtl_registry/entitlements.py`, `tests/fast/test_entitlements.py`, `scripts/dtl_concurrency_harness.py`*

#### `TEN-02` · Is a physically separate instance available?

**CUSTOMER_CONFIGURED**

Yes, by running the container in the customer's own environment. That is the strongest isolation available and it is the recommended option for a customer whose risk assessment does not accept logical separation.

*Evidence: `Dockerfile.web`*

### Encryption in transit

#### `CRY-01` · How is data protected in transit?

**PARTIALLY_IMPLEMENTED**

TLS is terminated by the hosting platform in front of the application, so the hosted service is HTTPS only. The application does not itself terminate TLS. In a customer-hosted deployment, transport security is the customer's to configure, which is stated here rather than assumed.

*Evidence: `railway.toml`*

### Encryption at rest

#### `CRY-02` · How is data protected at rest?

**PARTIALLY_IMPLEMENTED**

Database contents rely on the hosting platform's encryption at rest. Signing keys are separately encrypted when DTL_KEYSTORE_PASSPHRASE is set, and the status command reports honestly when it is not, rather than claiming a protection that is absent.

*Evidence: `modules/dtl_registry/keyring.py`, `tests/fast/test_keyring.py`*

### Signing key custody

#### `KEY-01` · Is there a defined key lifecycle?

**IMPLEMENTED**

Yes. PENDING, ACTIVE, RETIRED, REVOKED and DESTROYED, with metadata for algorithm, scope and every transition timestamp. Key identifiers are derived from the public key and are never reused.

*Evidence: `modules/dtl_registry/keyring.py`, `docs/security/KEY_CUSTODY_POLICY.md`, `tests/fast/test_keyring.py`*

#### `KEY-02` · Can a reviewer execute a rotation and inspect the result?

**IMPLEMENTED**

Yes, from a command line, offline, in under five minutes. A dry run reports the impact without changing state. Executed evidence from a real rotation, including the audit events and verification of packs from both sides of the boundary, is regenerated on demand.

*Evidence: `scripts/dtl_keyring_cli.py`, `docs/security/KEY_ROTATION_RUNBOOK.md`, `scripts/dtl_key_rotation_evidence.py`, `docs/security/evidence`*

#### `KEY-03` · Do historical evidence packs survive a rotation?

**IMPLEMENTED**

Yes. Each chain entry records the key identifier that signed it, and verification resolves that identifier rather than reaching for the current key. A test asserts that a pack signed before a rotation verifies after it, and a second test asserts that verifying the whole chain against only the current key fails, so the property cannot silently regress.

*Evidence: `modules/dtl_registry/attestation.py`, `tests/fast/test_keyring.py`*

#### `KEY-04` · What happens when a recorded key cannot be resolved?

**IMPLEMENTED**

Verification fails closed and the attempt is written to the audit trail. There is no fallback to another key, because falling back would convert a key compromise into a working forgery.

*Evidence: `modules/dtl_registry/keyring.py`, `tests/fast/test_keyring.py`*

#### `KEY-05` · Can private key material be exposed through any interface?

**IMPLEMENTED**

No interface returns it, no log line contains it, and it is not embedded in evidence packs. A test extracts the real private bytes and asserts their absence from the evidence envelope, operator status, the key listing, the exported public material, the audit trail, the public transparency slice and the keystore index.

*Evidence: `tests/fast/test_keyring.py`, `modules/dtl_registry/keyring.py`*

#### `KEY-06` · Is custody hardware-backed?

**PLANNED**

No. Keys are software keys held by the service. There is no HSM and no claim of one. A provider interface exists so that AWS KMS, Azure Key Vault, Google Cloud KMS or a PKCS#11 HSM can be added without changing what an evidence pack means, because packs reference a key identifier rather than key material. No such provider is configured today, and the status command reports hardware_backed as false.

*Evidence: `modules/dtl_registry/keyring.py`*

#### `KEY-07` · Is there segregation of duties over key operations?

**PLANNED**

No. EcoKure has one director, who requests, approves and performs every custody operation. This is a genuine gap and is recorded as one. The compensating control is that every operation writes an immutable audit event naming the actor, and the trail can be given to a customer for independent review.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`*

#### `KEY-08` · Is there an emergency revocation procedure?

**IMPLEMENTED**

Yes, with the ordering that matters: rotate first to restore a good signing identity, then contain, establish the exposure window from the recorded key identifiers, and only then revoke. Revocation requires a reason, which is published with the key status.

*Evidence: `docs/security/EMERGENCY_REVOCATION_RUNBOOK.md`, `modules/dtl_registry/keyring.py`*

#### `KEY-09` · Can concurrent operations produce an ambiguous active key?

**IMPLEMENTED**

No. Rotation takes a cross-process lock and the one-active-key invariant is asserted on every write. Tests drive eight concurrent threads and four concurrent processes at the same keystore and assert a single active key survives.

*Evidence: `tests/fast/test_keyring.py`, `modules/dtl_registry/keyring.py`*

#### `KEY-10` · Is a failed rotation recoverable?

**IMPLEMENTED**

Yes. The keystore index is written once, at the end, so a failure part way through leaves the incumbent active and records no partial key. A test injects a failure mid-rotation and asserts both, then asserts that a retry succeeds.

*Evidence: `tests/fast/test_keyring.py`*

### Identity and access control

#### `IAM-01` · How do customers authenticate?

**IMPLEMENTED**

A bearer API key presented in a header, bound to a tenant and an entitlement, scoped to the gates the customer bought. Keys are rotatable without disturbing the subscription, and rotation disables the previous credential immediately.

*Evidence: `modules/dtl_registry/apigate.py`, `modules/dtl_registry/onboarding.py`, `tests/fast/test_onboarding.py`*

#### `IAM-02` · Is single sign-on supported?

**PLANNED**

Not for the API, which is machine to machine and uses keys. SAML or OIDC for the administrative interface is not built.

*Evidence: `modules/dtl_registry/apigate_api.py`*

### Privileged access

#### `IAM-03` · Who has administrative access, and how is it controlled?

**PARTIALLY_IMPLEMENTED**

Key issuance requires a separate administrative secret supplied in a header, and is refused outright when that secret is not configured. Key custody operations are deliberately not exposed over HTTP at all, so they remain possible on a host that has been isolated during an incident. Administrative access is held by one person, which is a size problem rather than a design one, and is recorded as a gap under KEY-07.

*Evidence: `modules/dtl_registry/apigate_api.py`, `scripts/dtl_keyring_cli.py`*

### Access review

#### `IAM-04` · Are access rights reviewed periodically?

**PLANNED**

No formal review cycle exists. With one administrator there is nothing to review today, but this will not remain true and it is not presented as a control.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`*

### Secure development lifecycle

#### `SDL-01` · Is there automated security testing in CI?

**IMPLEMENTED**

Every pull request and every push to the main branch runs a fast verification suite, a dependency vulnerability audit with pip-audit, a Semgrep scan, and CodeQL analysis, followed by a container build. A failure blocks the merge.

*Evidence: `.github/workflows/production-release-gate.yml`, `requirements-security.txt`*

### Code review and change control

#### `SDL-02` · Is code independently reviewed before release?

**PARTIALLY_IMPLEMENTED**

Automated gates run on every change and cannot be skipped. Human peer review by a second person does not happen, because there is no second person. An external engineer conducted an architecture and code audit of the DTL system; that was a point-in-time review, not a penetration test and not a continuing assurance engagement, and it is described that way in ASR-01.

*Evidence: `.github/workflows/production-release-gate.yml`*

### Dependency and vulnerability management

#### `VUL-01` · How are vulnerable dependencies found and handled?

**PARTIALLY_IMPLEMENTED**

pip-audit runs against the pinned requirements on every build and fails it on a known vulnerability. An audit on 19 August 2026 reported fourteen advisories across five packages, four against the cryptography library the signing work depends on. Thirteen are now remediated: cryptography, starlette and click were upgraded, along with two packages whose own ceilings had been blocking those upgrades, and python-jose was removed because the code imports PyJWT and never used it, which also removed the unfixable ecdsa advisory it dragged in. One advisory remains and is accepted rather than suppressed: diskcache 5.6.3, unsafe pickle deserialisation, with no published fix. It arrives transitively through llama-cpp-python for its internal prompt cache, is not reachable from any gate or the signing path, and the advisory requires an attacker to already hold write access to the cache directory, at which point they have code execution by other means. Both audit runs are attached so a reviewer can see the before and after rather than our summary of them.

*Evidence: `.github/workflows/production-release-gate.yml`, `requirements.txt`, `docs/security/evidence/pip_audit_20260819.txt`, `docs/security/evidence/pip_audit_after_upgrade_20260819.txt`*

### Vulnerability disclosure

#### `VUL-02` · Is there a way to report a vulnerability?

**IMPLEMENTED**

A published security policy with reporting guidance.

*Evidence: `SECURITY.md`*

### SBOM

#### `SBM-01` · Is a software bill of materials available?

**IMPLEMENTED**

A CycloneDX 1.6 document covering 353 components is generated from the built environment, not from the requirements file, because the question a supply-chain reviewer is asking is what is actually present rather than what was asked for. CI regenerates it on every build and publishes it as a build artefact. It covers the Python environment only, and does not describe the base container image, system packages or model weights.

*Evidence: `docs/security/sbom/jarvi3-cyclonedx.json`, `scripts/generate_sbom.py`, `.github/workflows/production-release-gate.yml`, `docs/security/sbom/README.md`*

### Secrets management

#### `SEC-01` · How are secrets handled?

**PARTIALLY_IMPLEMENTED**

Secrets are supplied through environment variables from the hosting platform's secret store and are not committed. The keystore passphrase is held separately from any keystore backup. There is no dedicated secret manager such as Vault, and secret rotation outside the signing key is manual.

*Evidence: `modules/dtl_registry/keyring.py`, `.github/workflows/production-release-gate.yml`*

#### `SEC-02` · Is the repository scanned for committed secrets?

**PARTIALLY_IMPLEMENTED**

Semgrep and CodeQL run on every change and cover common secret patterns. A dedicated secret scanner with a full history sweep is not configured.

*Evidence: `.github/workflows/production-release-gate.yml`*

### Logging and tamper protection

#### `LOG-01` · What is logged, and can the log be altered?

**IMPLEMENTED**

Every verdict is appended to a hash chain whose head is signed, so altering any historical entry changes every subsequent head and is detectable by a single audit walk. This is the Certificate Transparency model applied to verification verdicts. Key custody operations write their own audit events.

*Evidence: `modules/dtl_registry/attestation.py`, `tests/fast/test_apigate_attestation.py`*

#### `LOG-02` · Can a customer verify the log independently?

**IMPLEMENTED**

Yes. An audit slice endpoint returns the entries and the public keys involved, including across a rotation boundary, and the verification function is pure and shipped so it can be run offline against material we never see.

*Evidence: `modules/dtl_registry/apigate_api.py`, `modules/dtl_registry/attestation.py`*

### Monitoring

#### `LOG-03` · Is there security monitoring and alerting?

**PLANNED**

Application logs and platform health checks exist. There is no security information and event management system, no alerting on anomalous authentication, and no on-call rotation.

*Evidence: `railway.toml`*

### Incident response

#### `IR-01` · Is there an incident response procedure?

**PARTIALLY_IMPLEMENTED**

A detailed procedure exists for the incident specific to this product, the compromise of the signing key, including containment ordering, exposure window determination, customer notification content and post-incident review. A general incident response plan covering other classes of incident is not written.

*Evidence: `docs/security/EMERGENCY_REVOCATION_RUNBOOK.md`*

### Breach notification

#### `IR-02` · What notification commitment applies?

**PARTIALLY_IMPLEMENTED**

For a signing key compromise, affected customers are notified with the key identifier, the exposure window, the replacement key and the re-verification path. Australian Notifiable Data Breaches obligations are assessed on any incident. A contractual notification window is negotiated per agreement and is not yet a standing published commitment.

*Evidence: `docs/security/EMERGENCY_REVOCATION_RUNBOOK.md`*

### Backup and recovery

#### `BCP-01` · How is the system backed up and restored?

**PARTIALLY_IMPLEMENTED**

Hosted deployments rely on the platform's managed database backups, which cover the keystore because it is stored there. Local deployments back up the keystore directory with the passphrase set, so private keys are encrypted before reaching the backup medium. Restoration is verified by running the chain verification, which is a stronger check than confirming files exist. Restore drills are not yet performed on a schedule.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`, `docs/security/EMERGENCY_REVOCATION_RUNBOOK.md`*

### Business continuity

#### `BCP-02` · What happens to customer evidence if the vendor disappears?

**IMPLEMENTED**

Evidence packs stay verifiable. Verification needs the pack and the published public key, and neither requires us to exist or to be reachable. This is a deliberate property rather than a consequence, and it is the honest answer to the concentration risk of buying from a company of this size.

*Evidence: `modules/dtl_registry/attestation.py`, `tests/fast/test_apigate_attestation.py`*

### Disaster recovery objectives

#### `BCP-03` · What are the recovery time and recovery point objectives?

**PLANNED**

No RTO or RPO is committed. Publishing a number that has never been tested would be worse than saying this.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`*

### Retention and deletion

#### `RET-01` · How long is data kept, and can it be deleted?

**PARTIALLY_IMPLEMENTED**

Submitted content is not retained. Tenant, entitlement and usage records are kept for the life of the relationship and can be deleted on request. Chain entries are deliberately not deletable, because an append-only log that can be edited proves nothing; they contain a hiding commitment rather than content, so there is nothing about the verification to disclose. A formal published retention schedule does not exist yet.

*Evidence: `modules/dtl_registry/attestation.py`, `modules/dtl_registry/entitlements.py`*

### Privacy

#### `PRV-01` · Is personal information processed?

**PARTIALLY_IMPLEMENTED**

Not by design. Content submitted for verification may contain personal information depending on what the customer sends, which is why it is not persisted and why the chain stores a commitment rather than a hash of it. A privacy policy is published. A formal data processing agreement template is not yet prepared.

*Evidence: `PRIVACY.md`, `modules/dtl_registry/attestation.py`*

### Data residency

#### `PRV-02` · Where is data hosted, and can residency be constrained?

**CUSTOMER_CONFIGURED**

For the hosted service, residency follows the hosting platform's region and is confirmed per agreement rather than asserted here. A customer with a hard residency requirement should take the on-premises or private-cloud deployment, where residency is entirely theirs.

*Evidence: `railway.toml`, `Dockerfile.web`*

### Sub-processors

#### `TPS-01` · Which third parties are involved?

**PARTIALLY_IMPLEMENTED**

For the hosted service: a container hosting platform and its managed database, a DNS and edge provider, and a source control and CI provider. The current list with legal entity names and processing purposes is maintained by the Director and provided under agreement rather than published here, because a stale published list is worse than a current supplied one. Customer-hosted deployments have no EcoKure sub-processors at all.

*Evidence: `railway.toml`, `.github/workflows/production-release-gate.yml`*

### Independent assurance

#### `ASR-01` · Has an independent security assessment been performed?

**PLANNED**

No penetration test has been performed and no independent security assurance engagement has been completed. An external engineer conducted an architecture and code audit of the DTL system, which is useful but is neither of those things, and it did not cover concurrency or load. Concurrency was subsequently tested by us, which found and fixed real defects, and that is our own testing, not third party validation.

*Evidence: `scripts/dtl_concurrency_harness.py`*

### Internal testing

#### `ASR-02` · What testing supports the security claims in this pack?

**IMPLEMENTED**

A fast test suite runs on every change. Key custody, attestation, entitlement and onboarding behaviour are covered by dedicated suites, including concurrency across threads and processes, injected-failure recovery, and an offline test that fails if any custody operation attempts a network connection. A separate harness exercises the metering and chain paths across multiple processes.

*Evidence: `tests/fast/test_keyring.py`, `tests/fast/test_apigate_attestation.py`, `tests/fast/test_entitlements.py`, `tests/fast/test_onboarding.py`, `scripts/dtl_concurrency_harness.py`*

### Certifications

#### `CRT-01` · Which certifications are held?

**PLANNED**

None. EcoKure holds no SOC 2 report, no ISO 27001 certification, no HIPAA attestation and no FedRAMP authorisation, and is not in an active certification process for any of them. A customer requiring certified vendors should treat this as disqualifying rather than as a roadmap item.

*Evidence: `docs/security/security_posture.yaml`*

### Regulatory alignment

#### `CRT-02` · Does the product help with regulatory obligations?

**PARTIALLY_IMPLEMENTED**

The product produces tamper-evident, independently verifiable records of verification decisions, which is evidence a customer can use in their own regulatory position. That is a different claim from EcoKure being certified, and the two should not be run together.

*Evidence: `modules/dtl_registry/attestation.py`*

### Availability and support

#### `AVL-01` · What availability and support commitment applies?

**PARTIALLY_IMPLEMENTED**

A support commitment is published with the enterprise package. There is no contractual uptime service level with credits, and no 24 by 7 on-call. For a customer-hosted deployment availability is theirs, and the gates run without contacting us.

*Evidence: `docs/PRODUCT_PACKAGE.md`*

### Overage behaviour

#### `AVL-02` · Does the service stop working when a limit is reached?

**IMPLEMENTED**

No. Consumption past an allowance is recorded and billed, never refused. A control system that stops verifying because a counter was reached is one nobody should deploy, so the behaviour is asserted by test rather than left to configuration.

*Evidence: `modules/dtl_registry/entitlements.py`, `tests/fast/test_entitlements.py`*

### Customer responsibilities

#### `CUS-01` · What must the customer do?

**CUSTOMER_CONFIGURED**

Protect API keys and rotate them on staff changes; retain issued evidence packs, including the nonce, since without it a pack cannot be tied to its chain entry; decide who may call which gates; and for customer-hosted deployments, own the host, backups, transport security and keystore passphrase custody.

*Evidence: `modules/dtl_registry/onboarding.py`, `docs/security/KEY_CUSTODY_POLICY.md`*

### Known limitations

#### `LIM-01` · What should a reviewer weigh against this vendor?

**IMPLEMENTED**

One director, so no segregation of duties and a real key person dependency. No independent penetration test and no certifications. One accepted dependency advisory with no published fix, assessed as unreachable rather than ignored. No SIEM, no committed recovery objectives, and no on-premises reference installation yet. Signing keys are software keys, not hardware backed. The mitigating structural fact is that evidence packs verify without us, so the failure of the vendor does not invalidate the evidence a customer already holds.

*Evidence: `docs/security/KEY_CUSTODY_POLICY.md`, `docs/security/security_posture.yaml`*

## Evidence index

| Control | Status | Evidence |
|---|---|---|
| `ORG-01` | IMPLEMENTED | `docs/security/KEY_CUSTODY_POLICY.md`<br>`README.md` |
| `ORG-02` | IMPLEMENTED | `docs/PROGRAMBENCH_HONEST_LOOP_HANDOFF.md`<br>`docs/TERMINALBENCH_HONEST_LOOP_HANDOFF.md` |
| `DEP-01` | IMPLEMENTED | `tests/fast/test_keyring.py`<br>`modules/dtl_registry/keyring.py` |
| `DEP-02` | PARTIALLY_IMPLEMENTED | `Dockerfile.web`<br>`railway.toml` |
| `DEP-03` | IMPLEMENTED | `docs/security/KEY_CUSTODY_POLICY.md` |
| `ARCH-01` | IMPLEMENTED | `docs/security/KEY_CUSTODY_POLICY.md`<br>`modules/dtl_registry/keyring.py` |
| `ARCH-02` | IMPLEMENTED | `modules/dtl_registry/attestation.py`<br>`tests/fast/test_apigate_attestation.py` |
| `DATA-01` | IMPLEMENTED | `modules/dtl_registry/entitlements.py`<br>`PRIVACY.md` |
| `DATA-02` | IMPLEMENTED | `modules/dtl_registry/attestation.py`<br>`tests/fast/test_apigate_attestation.py` |
| `DATA-03` | IMPLEMENTED | `modules/dtl_registry/attestation.py`<br>`modules/dtl_registry/entitlements.py` |
| `TEN-01` | IMPLEMENTED | `modules/dtl_registry/entitlements.py`<br>`tests/fast/test_entitlements.py`<br>`scripts/dtl_concurrency_harness.py` |
| `TEN-02` | CUSTOMER_CONFIGURED | `Dockerfile.web` |
| `CRY-01` | PARTIALLY_IMPLEMENTED | `railway.toml` |
| `CRY-02` | PARTIALLY_IMPLEMENTED | `modules/dtl_registry/keyring.py`<br>`tests/fast/test_keyring.py` |
| `KEY-01` | IMPLEMENTED | `modules/dtl_registry/keyring.py`<br>`docs/security/KEY_CUSTODY_POLICY.md`<br>`tests/fast/test_keyring.py` |
| `KEY-02` | IMPLEMENTED | `scripts/dtl_keyring_cli.py`<br>`docs/security/KEY_ROTATION_RUNBOOK.md`<br>`scripts/dtl_key_rotation_evidence.py`<br>`docs/security/evidence` |
| `KEY-03` | IMPLEMENTED | `modules/dtl_registry/attestation.py`<br>`tests/fast/test_keyring.py` |
| `KEY-04` | IMPLEMENTED | `modules/dtl_registry/keyring.py`<br>`tests/fast/test_keyring.py` |
| `KEY-05` | IMPLEMENTED | `tests/fast/test_keyring.py`<br>`modules/dtl_registry/keyring.py` |
| `KEY-06` | PLANNED | `modules/dtl_registry/keyring.py` |
| `KEY-07` | PLANNED | `docs/security/KEY_CUSTODY_POLICY.md` |
| `KEY-08` | IMPLEMENTED | `docs/security/EMERGENCY_REVOCATION_RUNBOOK.md`<br>`modules/dtl_registry/keyring.py` |
| `KEY-09` | IMPLEMENTED | `tests/fast/test_keyring.py`<br>`modules/dtl_registry/keyring.py` |
| `KEY-10` | IMPLEMENTED | `tests/fast/test_keyring.py` |
| `IAM-01` | IMPLEMENTED | `modules/dtl_registry/apigate.py`<br>`modules/dtl_registry/onboarding.py`<br>`tests/fast/test_onboarding.py` |
| `IAM-02` | PLANNED | `modules/dtl_registry/apigate_api.py` |
| `IAM-03` | PARTIALLY_IMPLEMENTED | `modules/dtl_registry/apigate_api.py`<br>`scripts/dtl_keyring_cli.py` |
| `IAM-04` | PLANNED | `docs/security/KEY_CUSTODY_POLICY.md` |
| `SDL-01` | IMPLEMENTED | `.github/workflows/production-release-gate.yml`<br>`requirements-security.txt` |
| `SDL-02` | PARTIALLY_IMPLEMENTED | `.github/workflows/production-release-gate.yml` |
| `VUL-01` | PARTIALLY_IMPLEMENTED | `.github/workflows/production-release-gate.yml`<br>`requirements.txt`<br>`docs/security/evidence/pip_audit_20260819.txt`<br>`docs/security/evidence/pip_audit_after_upgrade_20260819.txt` |
| `VUL-02` | IMPLEMENTED | `SECURITY.md` |
| `SBM-01` | IMPLEMENTED | `docs/security/sbom/jarvi3-cyclonedx.json`<br>`scripts/generate_sbom.py`<br>`.github/workflows/production-release-gate.yml`<br>`docs/security/sbom/README.md` |
| `SEC-01` | PARTIALLY_IMPLEMENTED | `modules/dtl_registry/keyring.py`<br>`.github/workflows/production-release-gate.yml` |
| `SEC-02` | PARTIALLY_IMPLEMENTED | `.github/workflows/production-release-gate.yml` |
| `LOG-01` | IMPLEMENTED | `modules/dtl_registry/attestation.py`<br>`tests/fast/test_apigate_attestation.py` |
| `LOG-02` | IMPLEMENTED | `modules/dtl_registry/apigate_api.py`<br>`modules/dtl_registry/attestation.py` |
| `LOG-03` | PLANNED | `railway.toml` |
| `IR-01` | PARTIALLY_IMPLEMENTED | `docs/security/EMERGENCY_REVOCATION_RUNBOOK.md` |
| `IR-02` | PARTIALLY_IMPLEMENTED | `docs/security/EMERGENCY_REVOCATION_RUNBOOK.md` |
| `BCP-01` | PARTIALLY_IMPLEMENTED | `docs/security/KEY_CUSTODY_POLICY.md`<br>`docs/security/EMERGENCY_REVOCATION_RUNBOOK.md` |
| `BCP-02` | IMPLEMENTED | `modules/dtl_registry/attestation.py`<br>`tests/fast/test_apigate_attestation.py` |
| `BCP-03` | PLANNED | `docs/security/KEY_CUSTODY_POLICY.md` |
| `RET-01` | PARTIALLY_IMPLEMENTED | `modules/dtl_registry/attestation.py`<br>`modules/dtl_registry/entitlements.py` |
| `PRV-01` | PARTIALLY_IMPLEMENTED | `PRIVACY.md`<br>`modules/dtl_registry/attestation.py` |
| `PRV-02` | CUSTOMER_CONFIGURED | `railway.toml`<br>`Dockerfile.web` |
| `TPS-01` | PARTIALLY_IMPLEMENTED | `railway.toml`<br>`.github/workflows/production-release-gate.yml` |
| `ASR-01` | PLANNED | `scripts/dtl_concurrency_harness.py` |
| `ASR-02` | IMPLEMENTED | `tests/fast/test_keyring.py`<br>`tests/fast/test_apigate_attestation.py`<br>`tests/fast/test_entitlements.py`<br>`tests/fast/test_onboarding.py`<br>`scripts/dtl_concurrency_harness.py` |
| `CRT-01` | PLANNED | `docs/security/security_posture.yaml` |
| `CRT-02` | PARTIALLY_IMPLEMENTED | `modules/dtl_registry/attestation.py` |
| `AVL-01` | PARTIALLY_IMPLEMENTED | `docs/PRODUCT_PACKAGE.md` |
| `AVL-02` | IMPLEMENTED | `modules/dtl_registry/entitlements.py`<br>`tests/fast/test_entitlements.py` |
| `CUS-01` | CUSTOMER_CONFIGURED | `modules/dtl_registry/onboarding.py`<br>`docs/security/KEY_CUSTODY_POLICY.md` |
| `LIM-01` | IMPLEMENTED | `docs/security/KEY_CUSTODY_POLICY.md`<br>`docs/security/security_posture.yaml` |

*Generated from `docs/security/security_posture.yaml` (version 1.0, reviewed 2026-08-19). A machine-readable copy with the same control ids is at `docs/security/security_posture.json`.*
