Gateman
Documentation/Read database passwords

Read database passwords

capability_id: db:read
display_name: Read database passwords
ui_capability_key: read_database_passwords
scope: db:read
endpoint:
  method: POST
  path: /db/get
operation: database_password.get
billable: true
environment: not_applicable

Purpose and authorization

db:read authorizes an application to retrieve one named database password through POST /db/get. It is a separate capability from secrets:read.

The application must authenticate with Contract v1 credentials and the authenticated application must have the db:read scope. Retrieval is application-scoped; database host, port, database name, user, charset, and connection handling remain the application's responsibility.

Implementation contract

Request

Send a Contract v1 authenticated POST request to /db/get with a JSON body containing exactly one logical name for the lookup:

POST /db/get
Content-Type: application/json
X-GM-App: app_example
X-GM-Ts: 1791748800
X-GM-Sig: <Contract-v1-signature>
X-GM-Credential-Request-ID: 0123456789abcdef0123456789abcdef
{
  "name": "primary"
}

The name is trimmed before validation and must match [a-zA-Z][a-zA-Z0-9_.-]{0,63}. It is at most 64 characters: the first character must be an ASCII letter, and remaining characters may be ASCII letters, digits, ., _, or -. A request must include the signed single-use X-GM-Credential-Request-ID required by this credential route. The request ID is a fresh lowercase 32-character hexadecimal value for each attempt. Contract v1 authentication headers and signing rules apply; see the authentication and contract references below.

Only one name can be requested per call. The endpoint does not list names, enumerate credentials, or provide bulk retrieval. Additional JSON fields are ignored by the current route; clients should send only the documented field.

Successful response: password available

When the requested value is available, the response is HTTP 200:

{
  "ok": true,
  "name": "primary",
  "password": "example-password"
}

Successful response: password unavailable

An unknown or otherwise unavailable logical name is intentionally omitted, not disclosed as a separate absence error. The response is HTTP 200:

{
  "ok": true,
  "name": "primary"
}

The password property is absent, rather than null, an empty string, or a fabricated value. Applications must distinguish an omitted property from an actual returned password by checking whether the property exists. Both successful response forms use Cache-Control: no-store.

Environment independence

Database passwords are environment-independent. /db/get has no environment selector, and official clients do not add one. A logical name refers to the application-scoped password configured under that name across the application's environments. Applications that need distinct values must use distinct logical names and keep their environment mapping locally.

Error outcomes

The omission rule applies only to credential absence. Genuine operational, authentication, validation, replay, entitlement, concurrency, and accounting failures remain errors:

ConditionHTTP responseContract meaning
Authentication failure401Authentication is missing, invalid, expired, or otherwise rejected.
Missing db:read scope401Scope not allowed.
Invalid JSON, missing name, or invalid name400Invalid JSON or Invalid request.
Invalid credential request ID401Invalid credential request ID.
Reused credential request ID409Credential request already used.
Credential retrieval unavailable503Credential retrieval unavailable.
Monthly operation allowance exhausted403monthly_operation_limit_reached.
Operation accounting unavailable503Operation accounting unavailable.
Application concurrency limit reached429app_concurrency_limit_exceeded.
Database password retrieval failed500Database password unavailable.

Operation and replay obligations

Every accepted lookup consumes one billable database_password.get operation, regardless of whether a password is returned. Authentication, validation and replay rejections do not consume an operation.

A credential-request identifier is single-use and may be consumed even when a subsequent failure prevents disclosure. If the outcome is uncertain, the application MUST NOT assume that no operation was charged. A new attempt requires a fresh identifier and signature and may consume another operation.

The credential request ID is signed and scoped to the application. An optional idempotency key does not make this credential request reusable or deduplicate it.

Implementation outcome

An implementation conforming to this capability:

  • authorizes db:read and calls POST /db/get with one validated logical name;
  • treats an HTTP 200 response without password as the intentional unavailable-credential result;
  • never infers absence from a 404 response for this route;
  • accounts for Gateman charging one billable database_password.get operation per accepted lookup, including when no password is returned;
  • preserves genuine errors and respects the HTTP Cache-Control: no-store response policy;
  • does not request database connection metadata; and
  • keeps returned plaintext in application-controlled memory only as long as needed, without logging or exposing it.

Implementation instructions for agents

  • An integration SHOULD use an official Gateman client where appropriate. A direct HTTP implementation MUST conform to Contract v1.
  • The integration MUST use authenticated POST /db/get with the application's db:read scope and one validated logical name per request.
  • The integration MUST generate a fresh signed, single-use lowercase 32-character hexadecimal X-GM-Credential-Request-ID for every attempt.
  • The integration SHOULD omit environment from /db/get requests. Database-password retrieval is environment-independent, and the endpoint does not use environment to select a password. The integration **MUST NOT** enumerate names or request more than one logical name per call.
  • The integration MUST treat HTTP 200 with password as a returned value and HTTP 200 without the password property as an unavailable value. It MUST preserve the requested logical name.
  • The integration MUST preserve genuine authentication, validation, replay, accounting, concurrency, and retrieval errors as errors; it **MUST NOT** convert them into an unavailable-password result.
  • The integration MUST account for Gateman charging one billable database_password.get operation per accepted lookup, whether or not password is present.
  • The integration SHOULD NOT automatically retry an uncertain disclosure. A deliberate retry policy MAY use a fresh request ID and signature and MUST NOT assume that the ambiguous attempt was unaccepted or unbilled.
  • The integration MUST protect returned plaintext and SHOULD keep it in memory only as long as needed; it MUST NOT log, commit, or expose it unnecessarily.
  • Database connection details and environment mapping MUST remain the application's responsibility; Gateman does not create database connections or supply connection parameters.

Reusable AGENTS.md block

<!-- gateman:begin capability=db:read -->
- Read one application-scoped database password with authenticated Contract v1
  `POST /db/get` using `db:read`.
- Send one validated logical `name` per request. Database passwords are
  environment-independent. Omit `environment` from requests; Gateman does
  not use it to select a password. Do not attempt enumeration or bulk
  retrieval.
- Include the signed, single-use lowercase 32-character hexadecimal
  `X-GM-Credential-Request-ID`; use a fresh ID and signature for every retry.
- Names MUST be trimmed before validation and match `[a-zA-Z][a-zA-Z0-9_.-]{0,63}`.
- HTTP `200` with `password` means a value was returned. HTTP `200` without
  the `password` property means the requested name is unknown or unavailable;
  do not expect a separate absence error.
- The integration MUST account for Gateman charging one
  `database_password.get` operation per accepted lookup, whether or not
  `password` is present. Authentication, validation, and replay rejections
  remain errors and do not consume an accepted lookup.
- Do not assume an ambiguous transport outcome was unaccepted or unbilled;
  do not reuse its request ID.
- Treat returned passwords as confidential plaintext: do not log, commit,
  expose, or retain them longer than needed. Database connection metadata and
  environment mapping remain application-owned.
- Full capability reference: https://docs.getgateman.com/capabilities/database-password.read/
<!-- gateman:end capability=db:read -->