Skip to content

API: Human auth

Capability state: humanAuth.challenge is staging-durable; humanAuth.verifyPasskey is fixture-rehearsed; humanAuth.faceMatchFallback is shape-only. Real WebAuthn, real biometric pipelines, and real session-binding are not operational (see 022 gap report item 15).

The human-auth operations cover Gestalt’s human presence model. Two lanes:

  • Private passkey lane — WebAuthn-style passkey assertion. No biometric material seen by Gestalt.
  • CPU face-match fallback — explicit-consent 1:1 fallback proofing with ephemeral embeddings only. No template storage. No 1:N search.

A successful presence flow produces a human presence receipt. Presence does not create standing on its own — see authority.md for how presence is bound to actor/vessel for sensitive approvals.

See concepts: glossary — HumanAuth.

Request a privacy-preserving passkey challenge for human presence.

POST /v1/human-auth/challenge
state: staging-durable
sdk_role: request a privacy-preserving passkey challenge for human presence
request_record: CloudHumanAuthChallengeRequest
responses: human_auth_challenge | receipt
interface HumanAuthChallengeRequest {
tenant?: GestaltRef;
subject?: GestaltRef; // e.g. "human_person:anna"
relying_party_id?: string; // e.g. "gestalt.local"
scopes?: string[]; // e.g. ["sensitive_approval"]
}
{
"operation": "humanAuth.challenge",
"outcome": "verified",
"body": {
"challenge": "human_auth_challenge:fixture_private_human_auth",
"biometricMaterialSeenByGestalt": false
},
"receipt": {...}
}

biometricMaterialSeenByGestalt: false is asserted explicitly because the privacy guarantee is part of the contract.

const challenge = await client.humanAuthChallenge({
tenant: "tenant_node:rheinwerk_calibration",
subject: "human_person:anna",
relying_party_id: "gestalt.local",
scopes: ["sensitive_approval"],
});

Verify signed passkey challenge and receive human presence receipt without biometric material.

POST /v1/human-auth/passkey/verify
state: fixture-rehearsed
sdk_role: verify signed passkey challenge and receive human presence receipt without biometric material
request_record: CloudHumanAuthPasskeyVerifyRequest
responses: human_presence_receipt | refusal | receipt
interface HumanAuthPasskeyVerifyRequest {
tenant?: GestaltRef;
challenge: GestaltRef;
passkey_binding?: GestaltRef;
relying_party_id?: string;
user_verified?: boolean;
credential_id_hash?: string;
}
{
"operation": "humanAuth.verifyPasskey",
"outcome": "admitted",
"body": {
"humanPresenceReceipt": "human_presence_receipt:fixture_private_presence",
"standingCreated": false,
"biometricMaterialSeenByGestalt": false
},
"receipt": {...}
}

standingCreated: false is asserted: a successful passkey verify proves presence; it does not grant standing.

const verified = await client.humanAuthVerifyPasskey({
tenant: "tenant_node:rheinwerk_calibration",
challenge: challenge.body.challenge,
passkey_binding: "passkey_binding:anna_platform_passkey_fixture",
relying_party_id: "gestalt.local",
user_verified: true,
credential_id_hash: "sha256:fixture_credential_id_hash_private",
});
// verified.body.humanPresenceReceipt

Record staging passkey revocation through hash-only lifecycle state after same-passkey HumanAuth presence, without raw credential or biometric material.

POST /v1/human-auth/passkey/revoke
state: staging-durable
sdk_role: record staging passkey revocation through hash-only lifecycle state after same-passkey HumanAuth presence without raw credential or biometric material
request_record: CloudHumanAuthPasskeyRevokeRequest
responses: passkey_lifecycle | passkey_binding | human_presence_receipt | refusal | receipt
interface HumanAuthPasskeyRevokeRequest {
tenant?: GestaltRef;
subject?: GestaltRef;
passkey_binding: GestaltRef;
human_presence_receipt: GestaltRef;
revocation_ref?: GestaltRef;
reason_hash: string; // sha256:... required
fixture?: boolean; // must be true
contains_customer_data?: boolean; // refused if true
contains_biometric_material?: boolean; // refused if true
raw_credential_id?: string; // refused if present
raw_attestation_object?: string; // refused if present
raw_client_data_json?: string; // refused if present
create_identity_binding_from_passkey?: boolean; // refused if true
create_standing_from_passkey?: boolean; // refused if true
create_company_authority_from_passkey?: boolean; // refused if true
enforce_runtime_overlay?: boolean;
}

The human_presence_receipt must be a same-passkey HumanAuth presence (scope passkey_revoke or passkey_lifecycle) over the target passkey_binding after local user verification, with no biometric data seen by Gestalt.

{
"operation": "humanAuth.passkeyRevoke",
"outcome": "admitted",
"body": {
"human_auth_passkey_lifecycle": "human_auth_passkey_lifecycle:...",
"passkey_binding": "passkey_binding:...",
"human_presence_receipt": "human_presence_receipt:...",
"status": "revoked",
"enforced_in_runtime_overlay": true,
"raw_credential_id_stored": false,
"raw_attestation_object_stored": false,
"raw_client_data_json_stored": false,
"raw_private_key_material_stored": false,
"raw_biometric_material_stored": false,
"identity_binding_created": false,
"standing_created": false,
"company_authority_created": false,
"durable_state": {...},
"production_admission": false
},
"receipt": {...}
}

When enforce_runtime_overlay: true, the runtime adds the revoked binding to its in-memory overlay so subsequent humanAuth.verifyPasskey and lifecycle calls against it refuse.

Refusal codes: human_auth_passkey_lifecycle_fixture_only, human_auth_passkey_lifecycle_raw_material_refused, human_auth_passkey_lifecycle_cannot_create_authority, human_auth_passkey_lifecycle_subject_mismatch, human_auth_passkey_lifecycle_hash_required, human_auth_passkey_binding_unknown, human_auth_passkey_lifecycle_presence_missing, human_auth_passkey_lifecycle_presence_invalid.

const revoked = await client.humanAuthPasskeyRevoke({
tenant: "tenant_node:rheinwerk_calibration",
subject: "human_person:anna",
passkey_binding: "passkey_binding:anna_platform_passkey_fixture",
human_presence_receipt: "human_presence_receipt:fixture_private_presence",
revocation_ref: "human_auth_passkey_lifecycle:fixture_revoke",
reason_hash: "sha256:fixture_passkey_revocation_reason",
fixture: true,
});

Record staging passkey rotation to a known replacement binding after replacement-passkey HumanAuth presence, without creating identity or standing.

POST /v1/human-auth/passkey/rotate
state: staging-durable
sdk_role: record staging passkey rotation to a known replacement binding after replacement-passkey HumanAuth presence without creating identity or standing
request_record: CloudHumanAuthPasskeyRotateRequest
responses: passkey_lifecycle | old_passkey_binding | replacement_passkey_binding | human_presence_receipt | refusal | receipt
interface HumanAuthPasskeyRotateRequest {
tenant?: GestaltRef;
subject?: GestaltRef;
old_passkey_binding: GestaltRef;
replacement_passkey_binding: GestaltRef; // must differ from old
human_presence_receipt: GestaltRef;
rotation_ref?: GestaltRef;
reason_hash: string; // sha256:... required
fixture?: boolean; // must be true
contains_customer_data?: boolean; // refused if true
contains_biometric_material?: boolean; // refused if true
raw_credential_id?: string; // refused if present
raw_attestation_object?: string; // refused if present
raw_client_data_json?: string; // refused if present
create_identity_binding_from_passkey?: boolean; // refused if true
create_standing_from_passkey?: boolean; // refused if true
create_company_authority_from_passkey?: boolean; // refused if true
enforce_runtime_overlay?: boolean;
}

The human_presence_receipt must cover the replacement passkey (scope passkey_rotate or passkey_lifecycle) with local user verification and no biometric material.

{
"operation": "humanAuth.passkeyRotate",
"outcome": "admitted",
"body": {
"human_auth_passkey_lifecycle": "human_auth_passkey_lifecycle:...",
"old_passkey_binding": "passkey_binding:...",
"replacement_passkey_binding": "passkey_binding:...",
"human_presence_receipt": "human_presence_receipt:...",
"status": "rotated",
"enforced_in_runtime_overlay": true,
"raw_credential_id_stored": false,
"...": "..."
},
"receipt": {...}
}

When enforce_runtime_overlay: true, the runtime overlays the rotation so verify/lifecycle calls against the old binding map to the replacement.

Refusal codes: human_auth_passkey_lifecycle_fixture_only, human_auth_passkey_lifecycle_raw_material_refused, human_auth_passkey_lifecycle_cannot_create_authority, human_auth_passkey_lifecycle_subject_mismatch, human_auth_passkey_lifecycle_same_binding, human_auth_passkey_lifecycle_hash_required, human_auth_passkey_lifecycle_replayed, human_auth_passkey_lifecycle_presence_missing, human_auth_passkey_lifecycle_presence_invalid.

const rotated = await client.humanAuthPasskeyRotate({
tenant: "tenant_node:rheinwerk_calibration",
subject: "human_person:anna",
old_passkey_binding: "passkey_binding:anna_platform_passkey_fixture",
replacement_passkey_binding: "passkey_binding:fixture_passkey_replacement",
human_presence_receipt: "human_presence_receipt:fixture_private_presence",
rotation_ref: "human_auth_passkey_lifecycle:fixture_rotate",
reason_hash: "sha256:fixture_passkey_rotation_reason",
fixture: true,
});

Submit explicit-consent 1:1 fallback proofing fixture and receive receipt/hash/score/caveat artifact only.

POST /v1/human-auth/face-match
state: shape-only
sdk_role: submit explicit-consent 1:1 fallback proofing fixture and receive receipt/hash/score/caveat artifact only
request_record: CloudHumanAuthFaceMatchRequest
responses: cpu_face_match_receipt | refusal | receipt
interface HumanAuthFaceMatchRequest {
tenant?: GestaltRef;
subject?: GestaltRef;
consent_ref?: GestaltRef; // explicit consent required
scenario?: "same-person" | "different-person" | "low-quality" | "spoof";
}
{
"operation": "humanAuth.faceMatchFallback",
"outcome": "admitted",
"body": {
"cpuFaceMatchReceipt": "cpu_face_match_receipt:fixture_cpu_face_match",
"standingCreated": false,
"rawImagesStored": false,
"biometricTemplatesStored": false,
"oneToManySearch": false
},
"receipt": {...}
}

The body asserts the privacy invariants explicitly:

  • rawImagesStored: false
  • biometricTemplatesStored: false
  • oneToManySearch: false
  • standingCreated: false

Refused with human_auth_face_match_consent_missing if no consent_ref is supplied. Consent is structurally required — not a configuration toggle.

const fallback = await client.humanAuthFaceMatch({
tenant: "tenant_node:rheinwerk_calibration",
subject: "human_person:anna",
consent_ref: "consent:fixture_cpu_face_match",
scenario: "same-person",
});

A human_presence_receipt:* (from passkey verify) or cpu_face_match_receipt:* (from face-match fallback) is consumed by two follow-on operations:

A presence receipt never by itself creates standing or delegation. That separation is constitutional.

human_auth_face_match_consent_missing
human_auth_passkey_user_not_verified
human_auth_passkey_binding_unknown
human_auth_challenge_expired
human_auth_challenge_replayed
m13_human_presence_cannot_create_standing (returned by authority.presenceApproval)