# Git signer membership

Resolve a known device signing key to current persona membership.


**Auth:** Own-device signed read, operation `resolve-git-signer`.
## Request and response

Angle-bracket values describe placeholders, including nested objects and numeric types; these are wire shapes, not captured service data. Replace them before sending.

```http
POST /v1/graph-keys/resolve-signer HTTP/1.1
Host: trust-staging.rebellion.systems
Content-Type: application/json

{
  "graphNodeId": "<own-node-id>",
  "targetGraphKeyId": "<known-signing-key-id>",
  "authorization": {
    "graphKeyId": "<device-id>",
    "nonce": "<fresh-random-nonce>",
    "signedAt": "<current-ISO-timestamp>",
    "signature": "<base64-DER-signature>"
  }
}
```

Response shape:

```json role="response"
{
  "certificate": "<issuer-signed-device-certificate>",
  "status": "<signed-status-bound-to-certificate-and-nonce>"
}
```




Status: **Ships**.

`POST /v1/graph-keys/resolve-signer` resolves an exact known device key after you have verified a commit signature locally.

| Field | Meaning |
| --- | --- |
| `graphNodeId` | Requesting device's own node ID, 64 lowercase hex characters |
| `targetGraphKeyId` | Exact locally verified signing key ID, 64 lowercase hex characters |
| `authorization` | Read operation `resolve-git-signer`, signed over the two fields above |

The requester must be a usable approved ordinary graph device; content-only keys cannot query. Use a fresh authorization nonce of 16–256 characters. Read freshness and query rate limits apply.

Success returns `{certificate, status}` in the [device certificate formats](/api/content-certificates). The status binds the complete certificate digest and the authorization nonce. Verify the certificate's public JWK and key ID against the locally verified commit signer, both issuer signatures, the pinned issuer, times and nonce.

Then query reachability from your own node to the certificate's `graphNodeId`. Locally verify a positive path with the expected question and pinned keys before displaying connected membership.

Unknown, inactive or unapproved graph-purpose targets return the same 404. Treat that as unavailable evidence. The endpoint accepts no commit bytes, digest or repository name; it exposes no prefix search or bulk directory.


**Does not establish**
This resolves current operator-attested membership. It does not prove commit-time authorization, human authorship, review or code safety. Commit timestamps are signer-controlled. A 404 is not signed proof of absence or historical revocation, and a negative reachability answer is only a signed report.

For OpenPGP signers, use [external signing keys](/api/external-keys). For an end-to-end workflow, see [the Git recipe](/build/git-signers).
