# platform attestor

Source: https://www.testifysec.com/docs/cilock/attestors/platform/

The cilock platform attestor binds an attestation to the TestifySec platform tenant and product it was produced under, and records which identity signed in. It is on by default and skips itself when there is no platform identity.

Records the TestifySec platform tenant and product a run is bound to, plus the signed-in email or a CI workflow-identity marker, and emits the product and tenant as in-toto subjects.

 

| Name | `platform` |
| --- | --- |
| Predicate type | `https://testifysec.com/attestations/platform/v0.1` |
| Lifecycle | `prematerial` |
| Default binary? | Yes |
| Recommended trace | off — no syscall tracing needed |
| Auto-attaches when | *Not auto-detected — attach explicitly with `-a`.* |

The facts in this box are generated from the CI/lock binary's own catalog (`cilock tools list`). Do not hand-edit — run `npm run gen:catalog`.

 

## What it captures

 

The attestor does not authenticate anything itself. It reads a binding that `cilock run` already resolved, from one of two sources:

 

1. A stored `cilock login` session for the platform URL (`--platform-url`, default `https://platform.testifysec.com`). The session supplies tenant, product and email.
 2. An ambient CI workflow OIDC identity (GitHub Actions or GitLab CI) with no stored session. `cilock run` marks the platform URL as trusted only after its own same-origin check. If the run-entry gate resolved a tenant and product for that URL, they are recorded; otherwise only `workflow_identity: true` is recorded and the platform resolves the product on upload.

 

Fields (the `json` tags on `Attestor`):

 

- `platform_url`: the platform the binding belongs to.
 - `tenant_id`, `tenant_name`: the tenant.
 - `product_id`, `product_name`: the product.
 - `email`: the signed-in user, from a stored session only.
 - `workflow_identity`: `true` when the run authenticated with an ambient CI workflow identity instead of a stored session.

 

Every field except `platform_url` is omitted when empty. The predicate carries no timestamp of its own; the DSSE signature and the TSA carry the signing time.

 

## When to use

 

You do not normally ask for it. `platform` is in the default attestor set (`environment,git,platform`), so every `cilock run` without `-a` that has a platform identity records it. The `testifysec-product:<id>` subject is what the platform's ingestion reads to link the attestation to your product.

 

## Flags

 

None. The binding comes from the `cilock login` session or the ambient workflow identity. `CILOCK_PLATFORM_URL` is set by `cilock run` for the attestor; setting it yourself does not create a binding, because the workflow-identity path also requires an in-process trust marker that only `cilock run` sets.

 

## Output shape

 

```json
{
  "platform_url": "https://platform.testifysec.com",
  "tenant_id": "6f1c2a9e-...",
  "tenant_name": "acme",
  "product_id": "0b7d41c3-...",
  "product_name": "payments-api",
  "email": "dev@acme.example"
}
```

 

Subjects: `testifysec-product:<product_id>` and `testifysec-tenant:<tenant_id>`, each the SHA-256 of the id. A subject is emitted only when its id is set.

 

## Gotchas

 

- **Dropped from the default set when it cannot run.** With `--offline`, with no session and no workflow identity, or a binary that does not register the attestor, `cilock run` removes `platform` from the auto defaults. Only the auto defaults are trimmed.
 - **An explicit `-a platform` is honoured as given.** If the binary does not register it, the run fails with "attestor not found". With no binding, the attestor returns a soft error: a warning, exit code 0, and no platform predicate.
 - **An empty binding is a skip, not an empty record.** A session or resolver that yields no URL, tenant, product or workflow identity is treated as no binding, so you never get a platform predicate without subjects.
 - **Workflow identity may carry no ids.** When the run-entry gate did not resolve a product, the predicate has `platform_url` and `workflow_identity: true` but no tenant or product subjects.
 - **Preset binaries.** The public `plugins/attestors/platform` package has no `init()`; the `cilock` binary registers it through its internal adapter. A binary built only from the public plugins (for example `cilock-all`) drops it from the defaults, with a warning when the run has a platform identity, so that run records no tenant binding.

 

## CLI example

 

```bash
cilock login
cilock run --step build -- make build
```

 

The collection includes a `https://testifysec.com/attestations/platform/v0.1` predicate bound to the logged-in tenant and product.

 

## See also

 

- [Connect to the platform](https://www.testifysec.com/docs/cilock/getting-started/connect-to-the-platform)
 - [Concepts: signing & identity](https://www.testifysec.com/docs/cilock/concepts/signing-and-identity)
 - [Catalog row](https://www.testifysec.com/docs/cilock/reference/attestor-catalog)

 

---

**This page is generated from the CI/lock tool catalog.** Don't edit it here — the source is [`attestation/detection/docs/platform.doc.md`](https://github.com/aflock-ai/rookery/edit/main/attestation/detection/docs/platform.doc.md) in [aflock-ai/rookery](https://github.com/aflock-ai/rookery). The same catalog powers `cilock tools show platform` in the CLI, so a single edit keeps the terminal and the website in sync.

[Edit this page →](https://github.com/aflock-ai/rookery/edit/main/attestation/detection/docs/platform.doc.md) ·  [Add a new tool →](https://github.com/aflock-ai/rookery/new/main/attestation/detection/docs)

When you open the pull request: if you are an **AI agent**, add the `ai-agent` label. If you are a **human**, add the `human` label.

Reference generated from the product documentation. Match commands and support details to your installed release.
