PHP integration contract and unresolved questions
The PHP authentication repository is absent from /workspaces. No actual PHP SQL, password parameters, HTTP library, environment names or token format were verified. A read-only lookup of the same-owner GitHub repository also returned HTTP 404. HTTP credential context is now hash-free: it cannot support the previous proposed local password verification flow. Obtain and test the real client contract before production onboarding; no compatible replacement password scheme is invented. The database tests are executable mock consumer contract tests, not evidence that the deployed PHP application already uses this API. Confirm the following with its owner before enabling traffic:
- Map legacy user_id/company_id and organizations to the UUID tenant/user contract; agree on backfill, collision handling and a controlled cutover.
- Confirm normalized email and username behavior, enabled/verification flags, lockout policy and required public user fields.
- Confirm bcrypt/Argon2 formats and local password_verify/rehash behavior; no hash conversion or local authentication bypass is provided by this API.
- Confirm session ID binding, cryptographic token verification, refresh rotation, expiry, logout-all and atomic refresh replay requirements.
- Confirm verification and reset entropy, email delivery, expiry, one-time consumption, session invalidation and error/retry expectations.
- Agree on service scopes, rotation cadence, secret storage, caller environment variables, end-to-end fixtures and rollback. Existing PHP environment names are unknown; example names below are illustrative.
| Consumer workflow | Endpoint | Scope | Executable contract evidence |
|---|---|---|---|
| User lookup/create/update | /users, /users/lookup, /users/{id} | users:read/create/update | test_users_authentication_and_isolation |
| Hash-free account status context (password verification blocked) | /auth/credentials/verify-context | auth:credential-verify | test_users_authentication_and_isolation |
| Login result/lockout | /auth/events | auth:events:write | test_lockout_and_verification |
| Session create/read/revoke | /sessions, /sessions/{id}, /sessions/{id}/revoke | sessions:write/read/revoke | test_sessions_reset_and_replay |
| Signup verification | /verification-tokens and /consume | verification:write/consume | test_lockout_and_verification |
| Password reset/session invalidation | /verification-tokens and /consume | verification:write/consume | test_sessions_reset_and_replay |
| Tenant isolation | every tenant route | server-derived tenant | test_users_authentication_and_isolation, test_expiry_conflicts_and_cross_tenant_writes |
| Refresh rotation/logout-all product contract | not exposed independently | unresolved | not verified |
All listed tests are in backend/tests/test_application.py and run on real MySQL, MariaDB and PostgreSQL servers. Paths in this matrix are relative to /api/v1. The deployed PHP service's operation list is unknown; this matrix must be reconciled against its actual SQL.
Illustrative PHP cURL lookup, requiring PHP ext-curl and a trusted CA store:
<?php
function lookupUser(string $email): array {
$base = getenv('DATABASE_API_BASE_URL');
$key = getenv('DATABASE_API_SERVICE_KEY');
if (!$base || !$key || !str_starts_with($base, 'https://')) {
throw new RuntimeException('Database API configuration missing');
}
$ch = curl_init(rtrim($base, '/') . '/api/v1/users/lookup');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode(['email' => $email], JSON_THROW_ON_ERROR),
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $key],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === false || $status >= 500 || $status === 429) {
throw new RuntimeException('Authentication dependency unavailable');
}
if ($status === 404) {
return []; // caller must use a uniform end-user login rejection
}
if ($status !== 200) {
throw new RuntimeException('Database API request rejected');
}
return json_decode($body, true, 32, JSON_THROW_ON_ERROR);
}
Do not log request headers, email bodies, returned credential context or curl error strings. This example makes no automatic retry. Only lookup may be retried with a small bounded backoff; writes require reconciliation as described in the API guide. 401/403 identify service configuration failure, not an end-user bad password. A 5xx, transport error or timeout is a dependency failure. Credential context must never pass through the PHP application's public JSON response or logs.