A historical warehouse says MaxDPD_90d = 12 for a decision made at 2026-08-18 14:00. Production would have seen 28: the payment correction that reduced DPD had not reached the institution yet. Both values describe the same economic period; only one was available to the model.
Observation windows and availability windows are not the same
For feature X, WX(Td) defines the economic period it may inspect. A governed 90-day convention might be (Td−90d, Td]. The timestamp basis and inclusive boundaries must be explicit.
WHERE effective_time > :decision_time - INTERVAL '90 days'
AND effective_time <= :decision_time
AND available_time <= :decision_timeEffective time alone leaks later-known corrections. Load time alone can admit a future-effective change. Both axes are mandatory. For intraday decisions, a date is not a timestamp: an 18:00 event must not enter a 10:00 feature because they share a date.
An end-of-day snapshot can leak thirteen hours into a morning decision
DECISION CUT-OFFfuture same-day events →23:59
EOD SNAPSHOT
A table named customer_state_daily says nothing about its usable cut-off. Every snapshot needs effective_as_of and available_as_of, not only snapshot_date.
| Join | Leakage |
|---|---|
| effective_time ≤ decision_time | Includes records learned later |
| loaded_at ≤ decision_time | May include future-effective state |
| snapshot_date = decision_date | Includes later same-day facts |
| historical decision → current master | Injects current identity, segment and ownership |
Resolve historical membership before aggregating historical events
The reverse—aggregate today's canonical entities and attach an old decision date—creates identity and relationship leakage. A later party merge can consolidate exposure production saw separately; a later co-borrower edge can introduce an unknown facility.
SELECT ...
FROM decisions d
JOIN customer_attribute_history a
ON a.party_id = d.party_id
AND a.valid_from <= d.decision_time
AND (a.valid_to IS NULL OR a.valid_to > d.decision_time)
AND a.system_from <= d.decision_time
AND (a.system_to IS NULL OR a.system_to > d.decision_time);SCD Type 2 preserves validity but not necessarily when a backdated correction became known. Critical mutable dimensions need valid and system time. Historical exposure includes only known, valid facility relationships and point-in-time state.
Event features count eligible events; state features reconstruct the path
| Feature | Required history | PIT control |
|---|---|---|
| PaymentCount_90d | Discrete payment events | Finality, effective time, availability and reversal semantics |
| PaymentRatio_90d | Payments, schedule and allocation | Eligible numerator and denominator under one state mode |
| MaxDPD_180d | Historical delinquency path | Known DPD states or schedule/payment replay |
| AverageUtilisation_30d | Utilisation state path | Time-weighted intervals or documented daily approximation |
| TotalInternalDrawn | Historical facility membership and state | Resolve entity membership before aggregation |
Current DPD cannot produce historical max DPD, and start/end utilisation cannot produce average utilisation. Store constant-state intervals where precision matters:
A daily approximation can be valid methodology, but document it rather than claiming continuous-time exactness.
Observation ends before performance begins
CUT-OFFPERFORMANCE WINDOWT → T+12m
Future default, restructuring, collections outcomes and post-decision payments cannot enter features. Labels may use eventual restated outcomes, but methodology must say so. If data end before Td + horizon, the row is censored—not automatically non-default.
The dataset manifest declares which historical world was built
type FeatureDatasetManifest = {
datasetId: string;
generatedAt: Date;
populationStart: Date;
populationEnd: Date;
decisionTimeField: string;
featureSetVersion: string;
stateMode: "KNOWN" | "RESTATED";
labelDefinitionVersion: string;
performanceHorizon: string;
};Given the manifest and governed sources, the dataset should rebuild. A hash of schema, row keys and metadata can detect mutation but cannot replace lineage. Do not combine restated DPD, known exposure and today's identity into a synthetic past.
One semantic builder should serve research, validation and replay
buildFeatureVector({
entityId,
decisionTime,
featureSetVersion,
stateMode: "KNOWN"
});name: payment_count_90d
entity: facility
source_event: PAYMENT_APPLIED
window: 90d
time_basis: effective_time
availability_constraint: true
aggregation: count
version: v1A declarative registry pins source, grain, window, aggregation and null handling without requiring a full feature DSL. Where research SQL and production code remain separate, equivalence tests are mandatory.
SELECT d.decision_id, COUNT(e.event_id) AS payment_count_90d
FROM decisions d
LEFT JOIN financial_events e
ON e.facility_id = d.facility_id
AND e.event_type = 'PAYMENT_APPLIED'
AND e.effective_time > d.decision_time - INTERVAL '90 days'
AND e.effective_time <= d.decision_time
AND e.available_time <= d.decision_time
GROUP BY d.decision_id;One feature can have known and corrected histories
Latest immutable revision available by T. Replicates production information.
Current best economic reconstruction after corrections.
Controlled simulation of faster availability or better resolution.
Keep a feature_revision_id or system-time chain rather than overwriting a row. A production-like backfill reconstructs historical availability; a restated backfill uses corrected knowledge. The choice of known or restated training must be intentional.
The training-serving time contract is part of the model
Record effective time, available time and state mode. Refresh improvements can shift distributions even when model code is unchanged; treat them as data-generating-process and infrastructure-version changes requiring validation. Improved identity resolution and upstream semantic changes can do the same.
Leakage has six engineering forms
Prioritise deep PIT review for DPD, payment behaviour, utilisation, internal exposure, bureau and cross-entity features where temporal complexity is higher.
Temporal unit tests attack every boundary where leakage hides
| Test | Expected result |
|---|---|
| Cut-off | Event at 14:00:01 is excluded from a 14:00 decision |
| Timestamp tie | Explicit ordering governs an event exactly at T |
| Late event | Monday-effective, Wednesday-available event is excluded on Tuesday |
| Restated mode | The same event can enter Tuesday’s corrected feature |
| Window boundary | Event exactly T−90d follows the declared rule |
| Identity correction | Decision before merge uses old mapping |
| Facility creation | Facility opened after T never enters exposure |
| Reversal | Payment feature follows each decision-time state |
| End-of-day | 18:00 event never enters a 10:00 daily feature |
| Future sentinel | Synthetic post-cut-off event has zero influence |
A golden timeline makes temporal correctness executable
Fix expected payment count, ratio, DPD, utilisation and exposure at each decision. Build a small golden dataset with fixed rows, features and labels. Any code change must reproduce it unless intentionally versioned.
Model validation must test whether the dataset was possible
A statistically strong model trained on impossible information is operationally invalid. Audit each feature’s entity grain, sources, window, timestamp basis, availability constraint, identity semantics and label relationship.
| Step | Evidence |
|---|---|
| Identify | Affected definitions, revisions and datasets |
| Rebuild | Correct known-state PIT dataset |
| Measure | Performance and calibration change |
| Assess | Historical and prospective decision impact |
| Remediate | Retrain, revalidate or constrain use as required |
Monitor point-in-time integrity as an ongoing control
No universal thresholds apply. Compare reconstructed features with stored production snapshots, monitor revision impact by feature and cohort, and run fixed replay cases after identity, state, pipeline or schema changes.
The Entimema architecture filters knowledge before computing features
- Anchor decision time
- Resolve historical entity state
- Define observation window
- Filter effective time
- Filter availability time
- Compute pinned feature version
- Freeze snapshot
- Separate performance window
- Test leakage boundaries
- Validate replay
A Point-in-Time Feature Validation Agent can find impossible historical inputs
A controlled agent can inspect temporal definitions, validate window boundaries, detect availability violations, compare reconstructed with stored features, find current-master, identity and relationship leakage, test late events and same-day cut-offs, and identify affected models and datasets.
Credit Risk
Validate temporal legitimacy alongside discrimination, calibration and stability.
Decision Automation
Financial Data
Maintain bitemporal events, identity, relationships and state.
Continue with Building a Credit Risk Feature Store That Actually Respects Time, Point-in-Time Customer State Reconstruction, Event Time vs Processing Time vs Posting Time, Building a Reliable DPD Engine, Late-Arriving Events and Backdated Corrections and Why Customer ID Is Not Enough. Event-driven risk, streaming features and infrastructure-driven feature drift remain future research directions—not fabricated routes.