create schema if not exists kbx;

create table if not exists kbx.external_data_cache (
  tenant_id uuid not null,
  dataset_id text not null,
  provider_id text not null,
  cache_key text not null,
  request_descriptor jsonb not null,
  normalized_data jsonb not null,
  provider_observed_at timestamptz null,
  requested_at timestamptz not null,
  received_at timestamptz not null,
  ingested_at timestamptz not null,
  fresh_until timestamptz null,
  usable_until timestamptz null,
  payload_sha256 char(64) not null,
  normalizer_version text not null,
  state text not null check(state in ('fresh','stale','expired','unavailable')),
  correlation_id text not null,
  primary key(tenant_id,dataset_id,cache_key),
  check(usable_until is null or fresh_until is null or usable_until >= fresh_until)
);
create index if not exists ix_external_data_cache_state on kbx.external_data_cache(tenant_id,dataset_id,state,fresh_until);

create table if not exists kbx.external_data_observations (
  id bigint generated always as identity primary key,
  tenant_id uuid not null,
  dataset_id text not null,
  provider_id text not null,
  cache_key text not null,
  payload_sha256 char(64) not null,
  normalizer_version text not null,
  provider_observed_at timestamptz null,
  received_at timestamptz not null,
  ingested_at timestamptz not null,
  state text not null,
  correlation_id text not null
);
create index if not exists ix_external_data_observations_lookup on kbx.external_data_observations(tenant_id,dataset_id,cache_key,ingested_at desc);

comment on table kbx.external_data_cache is 'External provider normalized read cache. It is not domain truth and does not retain raw provider payload by default.';
comment on column kbx.external_data_cache.payload_sha256 is 'Evidence hash for reproducibility without default raw payload retention.';

comment on column kbx.external_data_cache.request_descriptor is 'Canonical non-secret request inputs only. Credentials, bearer tokens, and provider secrets are forbidden.';
