docs: define opaque payer token handling
This commit is contained in:
@@ -11,6 +11,7 @@ For every Go-related task, always invoke and follow the `golang-how-to` skill, t
|
|||||||
- The backend is the authority for authentication, authorization, tenant isolation, metric definitions, and data provenance.
|
- The backend is the authority for authentication, authorization, tenant isolation, metric definitions, and data provenance.
|
||||||
- Every merchant-scoped query derives merchant identity from the authenticated server-side session; never trust a client-supplied merchant identifier as authorization.
|
- Every merchant-scoped query derives merchant identity from the authenticated server-side session; never trust a client-supplied merchant identifier as authorization.
|
||||||
- Cross-merchant results are minimum-cohort, anonymized aggregates only.
|
- Cross-merchant results are minimum-cohort, anonymized aggregates only.
|
||||||
|
- Treat `payer_card_key` as an opaque, merchant-scoped source token with unverified upstream semantics. Retain it unchanged only for internal deterministic analytics; never expose it through merchant APIs, logs, exports, or AI inputs, and never describe it as a card number or verified person identifier.
|
||||||
- Use integer minor currency units or an explicitly documented fixed-precision representation; never floating point for money.
|
- Use integer minor currency units or an explicitly documented fixed-precision representation; never floating point for money.
|
||||||
- Interpret timezone-naive challenge timestamps as `Asia/Tehran`, preserve their source provenance, and normalize canonical database/API timestamps to UTC `timestamptz`/ISO 8601. Any change to this assumption requires a new import version and ADR.
|
- Interpret timezone-naive challenge timestamps as `Asia/Tehran`, preserve their source provenance, and normalize canonical database/API timestamps to UTC `timestamptz`/ISO 8601. Any change to this assumption requires a new import version and ADR.
|
||||||
- Raw imports are immutable inputs; corrections are new import versions, not silent mutation.
|
- Raw imports are immutable inputs; corrections are new import versions, not silent mutation.
|
||||||
|
|||||||
@@ -154,8 +154,9 @@ Resolved: use Ent for application persistence/modeling and pgx/PostgreSQL `COPY`
|
|||||||
|
|
||||||
Resolved: interpret timezone-naive source timestamps as `Asia/Tehran`, normalize canonical timestamps to UTC, expose ISO-8601 timestamps through APIs, and retain the immutable source/import provenance needed to reproduce the conversion. See ADR 0004.
|
Resolved: interpret timezone-naive source timestamps as `Asia/Tehran`, normalize canonical timestamps to UTC, expose ISO-8601 timestamps through APIs, and retain the immutable source/import provenance needed to reproduce the conversion. See ADR 0004.
|
||||||
|
|
||||||
|
Resolved: retain `payer_card_key` unchanged as a restricted, merchant-scoped opaque source token for internal repeat-payer analytics. Do not HMAC it, expose it, log it, export it, or send it to AI providers. Its upstream semantics remain unverified. See ADR 0005.
|
||||||
|
|
||||||
Remaining approval gates:
|
Remaining approval gates:
|
||||||
|
|
||||||
1. Whether `payer_card_key` must be retained, irreversibly transformed, or omitted after derived analytics.
|
1. Minimum cohort size and suppression policy for peer benchmarks.
|
||||||
2. Minimum cohort size and suppression policy for peer benchmarks.
|
2. Physical partitioning/materialization strategy, which must follow measured query needs rather than the logical ERD alone.
|
||||||
3. Physical partitioning/materialization strategy, which must follow measured query needs rather than the logical ERD alone.
|
|
||||||
|
|||||||
27
docs/decisions/0005-retain-opaque-payer-token.md
Normal file
27
docs/decisions/0005-retain-opaque-payer-token.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# ADR 0005: Retain the opaque payer token without additional pseudonymization
|
||||||
|
|
||||||
|
- Status: Accepted
|
||||||
|
- Date: 2026-08-20
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The dataset does not document the semantics or generation method of `payer_card_key`. Profiling found 1,034,368 populated rows and 402,173 distinct values. Values are opaque alphanumeric tokens 6–11 characters long. They repeat within a merchant, enabling repeat-payer analysis, but no observed token appears under multiple merchants. Approximately 53% of rows are missing the value.
|
||||||
|
|
||||||
|
Applying HMAC would preserve equality while adding secret storage, rotation, and re-import operations. Because the supplied value is already opaque and empirically merchant-scoped, that extra transformation provides limited benefit for this dataset and does not make the identifier anonymous.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
Retain the supplied `payer_card_key` unchanged as a nullable, restricted internal analytical field. Treat it only as an opaque merchant-scoped token with unverified upstream semantics.
|
||||||
|
|
||||||
|
Every lookup, grouping, or uniqueness calculation involving the token must include the merchant boundary. The token must never be returned by merchant-facing APIs, written to logs or traces, included in exports, rendered in the frontend, or sent to AvalAI/another third party. It must not be described as a card number, account number, or verified unique person.
|
||||||
|
|
||||||
|
Metrics derived from it must disclose source coverage and use language such as “شناسه پرداختکننده در دادههای موجود,” not claims about verified customers. A production source contract or evidence of reversibility/cross-merchant linkability triggers a new security review and ADR.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- Repeat-token frequency, retry, success, and approximate returning-payer analyses remain possible.
|
||||||
|
- No new pseudonymization secret or rotation workflow is required for the hackathon dataset.
|
||||||
|
- Database access remains more privileged than dashboard/API access because the token is still linkable behavioral data.
|
||||||
|
- Missing coverage prevents treating distinct-token counts as complete payer counts.
|
||||||
|
- Tests must verify tenant scoping and assert that DTOs, logs, exports, and AI payloads cannot contain the field.
|
||||||
|
|
||||||
Reference in New Issue
Block a user