# DCP-Cine Player anonymous discovery API

Available in player 4.2.20. Use this endpoint to identify a player during a device
scan without obtaining a login session or API token. This is an HTTP probe;
it does not introduce multicast discovery or initiate a subnet/device scan.

## Read endpoints

| Method and path | Response |
| --- | --- |
| GET /api/player/v1/discovery | Minimal JSON identity and public leaf certificate |
| GET /.well-known/dcp-cine-player | Alias of the discovery JSON endpoint |
| GET /api/player/v1/discovery/recipient-certificate | Public leaf PEM download |
| GET /.well-known/dcp-cine-player/recipient-certificate | Alias of the PEM download |

HEAD is also supported for each path. No authentication or playback/ingest licence
is required. Other native endpoints retain their existing authentication and
permissions, including device-info, status and the original identity/certificate
routes. The anonymous exception is restricted to exact read paths; it does not
open adjacent routes, configuration or control operations. Discovery supports no
write operation. Authenticated attempts to POST/PUT/PATCH/DELETE return 405;
anonymous non-read attempts to the /api paths remain authentication-blocked.

All responses send Cache-Control: no-store. JSON uses application/json; the PEM
endpoint uses application/x-pem-file. Discovery returns 200 even when optional
metadata or a certificate is unavailable. The affected values are null and
warnings identify unavailable/invalid fields. A certificate download returns
structured 503 RECIPIENT_CERTIFICATE_UNAVAILABLE when the leaf is absent,
malformed, unreadable, non-regular or exceeds the 64 KiB read limit.

## JSON fields

| Field | Meaning |
| --- | --- |
| schema | d-cine.player-api.discovery.v1; validate this to distinguish a player from a generic web/login page |
| product | Actual product: dcp-cine-player |
| version | Running player service build version; detailed component versions require authenticated device-info |
| device_id | Persisted installation UUID, or null if optional identity storage is unavailable |
| serial_number | Licence-issued product serial, or null for an unregistered/deactivated demo |
| sampled_at_utc | Snapshot timestamp, RFC3339 UTC |
| recipient_certificate | Public leaf metadata/PEM object, or null |
| endpoints | Relative paths for authenticated device-info and anonymous PEM download |
| warnings | Structured code/path pairs; no internal errors or filesystem paths |

The certificate object contains pem, fingerprint_sha256, certificate_serial_number,
not_before_utc and not_after_utc. The fingerprint is SHA-256 of the DER certificate.
The PEM contains exactly one public certificate with no PEM headers, private key
or chain. Certificate serial is distinct from the licence-issued product serial;
certificate rotation may change it while product serial and installation UUID stay
unchanged. The licence serial is read from the cached registration, never derived
from this certificate or old operator serial metadata.

A registered expired licence retains its issued identity. A demo may have an old
public certificate on disk while serial_number is null. Certificate presence
therefore does not establish an active licence, certificate validity/trust or KDM
authorisation; consumers can inspect the certificate validity and issuer chain
through their normal recipient verification workflow. Discovery does not rotate
keys/certificates, modify registration or confer playback permission.

No playback state, content catalogue, screen/site/contact details, audio settings,
connected equipment, network configuration, licence code/token, private key or
control credentials are included. The same internal identity provider supplies
native device-info and SOAP; discovery projects only the documented public fields.
Reads use persisted/cached identity plus a bounded local leaf-certificate read,
and send no control, discovery, remote-device or authority requests.

## Scanner examples

```sh
curl --fail --max-time 2 http://10.30.1.71:8080/api/player/v1/discovery
curl --fail --max-time 2 http://10.30.1.71:8080/.well-known/dcp-cine-player
curl --fail --max-time 2 http://10.30.1.71:8080/api/player/v1/discovery/recipient-certificate --output recipient.pem
```

On each candidate host/port, GET discovery with a bounded timeout; accept it only
when the JSON schema/product match. Read version, device_id, serial_number and the
certificate object. Use null for unknown values. Keep the installation UUID as
identity evidence; serial numbers follow licence registration and certificate
fingerprints follow recipient identity. Then use configured credentials for any
operational monitoring, detailed metadata or control.

Illustrative unregistered-demo response (not an installed screen reading):

```json
{
  "schema": "d-cine.player-api.discovery.v1",
  "product": "dcp-cine-player",
  "version": "4.2.20",
  "device_id": "urn:uuid:29ecba4a-3dc6-4d3c-9075-cda7799268c5",
  "serial_number": null,
  "sampled_at_utc": "2026-10-13T04:00:00Z",
  "recipient_certificate": null,
  "endpoints": {
    "device_info": "/api/player/v1/device-info",
    "recipient_certificate": "/api/player/v1/discovery/recipient-certificate"
  },
  "warnings": [{"code": "RECIPIENT_CERTIFICATE_UNAVAILABLE", "path": "recipient_certificate"}]
}
```

Concrete schemas and anonymous security declarations are included in
[player-api.openapi.json](player-api.openapi.json). Authenticated clients can
download this guide through /api/player/v1/schemas/player-discovery-api.md or the
combined /api/player/v1/tms/handoff. The Debian package ships the guide in its
player-api and documentation directories.

## Qualification

Go discovery tests cover anonymous reads and aliases, HEAD, protected-route
isolation, non-read rejection, demos with legacy serial metadata, licence/product
versus certificate serial, isolated certificate rotation, missing/oversized
certificates, canonical PEM without appended keys/headers, partial metadata
storage failure and cached reads during simulated playback without commands or
audit writes. Reproduce with go test ./cmd/dcp-player-service -run PublicDiscovery
from player-service. The contract tests validate discovery examples and the exact
anonymous OpenAPI operations; live evidence is recorded after installation.
