> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datafog.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Credential URIs

> Detect PostgreSQL connection URIs containing an explicit password.

<Note>`CREDENTIAL_URI` was added in Core 0.4.1.</Note>

`CREDENTIAL_URI` runs by default in text and structured scans across all four
runtimes. It recognizes `postgres://` and `postgresql://` (ASCII case insensitive)
with an explicit colon and nonempty password in the authority's user information.
An empty username is accepted. The finding covers the **whole URI**, including
its path and query, and retains the exact source casing and percent encoding.
No credentials are decoded or normalized for returned text or offsets.

This is lexical recognition of a scoped URI form. It does not connect to a
server, validate credentials, check query parameter names, or establish that
libpq can use the URI. A decimal port is recognized even if its numerical value
is outside the network-port range. Percent-encoded bytes, including `%00`, remain
opaque; malformed percent triplets are rejected.

## Scan and redact

```python theme={null}
from datafog_core import scan_and_transform

text = "DB=postgresql://app:p%40ss@db.example.com:5432/app?sslmode=require"
result = scan_and_transform(text, {
    "transform": {
        "default": {"strategy": "redact"},
        "entities": ["CREDENTIAL_URI"],
    }
})
assert result.text == "DB=[CREDENTIAL_URI]"
```

```javascript theme={null}
// Node; browser WASM uses the same operation after await init().
import { scanAndTransform } from "@datafog/node";
const result = scanAndTransform("DB=postgres://app:secret@localhost/app", {
  transform: { default: { strategy: "redact" }, entities: ["CREDENTIAL_URI"] },
});
console.assert(result.text === "DB=[CREDENTIAL_URI]");
```

Rust uses the same label with `scan` and `transform` or `scan_and_transform`.
Structured scanning applies the same rules independently to each string leaf;
field names do not supply missing credentials or combine separate URI pieces.

## Recognized syntax and boundaries

* A single ASCII hostname (including underscore), IPv4 address, or bracketed
  IPv6 address is supported. Hostname labels cannot be empty or start/end with a
  hyphen. Labels are limited to 63 bytes and the host to 253 bytes; a final
  hostname dot is accepted. An omitted host uses the recognizable
  libpq local-default shape, such as `postgres://app:secret@/app`.
* A port, when supplied after a colon, must contain one or more ASCII digits.
  No port range or connectivity check is performed.
* User information, paths, and queries accept RFC 3986 component characters and
  valid `%HH` triplets. Non-ASCII user information, paths, and queries must be
  percent encoded; hostnames must use their ASCII representation. Surrounding
  Unicode text retains correct byte, code-point, and
  JavaScript UTF-16 offsets.
* Whitespace, double quotes, angle brackets, braces, and backticks delimit a URI.
  Single quotes delimit it when the scheme immediately follows an opening single
  quote; otherwise an apostrophe can occur as URI data. Matching enclosing
  parentheses or square brackets are excluded from the finding. Bracketed IPv6
  hosts and parentheses inside a URI are retained.
* RFC-valid final punctuation in a path or query is retained. For example,
  `postgres://app:secret@db/app,` includes the final comma. Prose punctuation and
  URI data are ambiguous; use explicit quoting when a precise boundary matters.
* A scheme embedded in an ASCII identifier or another scheme prefix is rejected.
  Invalid percent encoding, authority syntax, ports, or suffixes reject the
  candidate rather than emitting a shortened valid prefix.

## Initial exclusions

Passwordless URIs, query-only passwords, fragments (`#...`), raw Unicode URI
content, raw `@` within passwords, other schemes, JDBC prefixes, general
`host=... password=...` connection strings, multiple hosts, percent-encoded Unix
socket hosts, and IPv6 zone identifiers are outside this initial scope. Encode
reserved password characters such as `@` as `%40`. The detector is intentionally
narrower than all connection strings accepted by PostgreSQL.

The grammar is informed by the official
[PostgreSQL connection URI documentation](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS)
and [RFC 3986 component syntax](https://www.rfc-editor.org/rfc/rfc3986#section-3).

## Findings and transformations

Findings use `datafog-core/credential-uri` provenance, the package detector
version, and no confidence score. Capability contract version 1 advertises the
label with `default` activation and both `text` and `structured` scopes.

Scans retain any overlapping EMAIL, PHONE, or numeric findings. The existing
transformation rules select the enclosing URI without introducing new detector
priorities. An explicit `entities: ["CREDENTIAL_URI"]` selection transforms only
these URI findings. Exact allowlists must contain the complete original encoded
URI, including any punctuation in its span. Redaction, removal, masking, and
native provider-backed pseudonymization/tokenization all operate on that whole
span; WASM retains its existing provider limitations.
