Merge pull request #543
masterplan-lock / check (push) Successful in 6s
Release chain (G17, ADR-W16-003) / Build, push, G17 (SBOM/scan/attest/verify/evidence) (push) Failing after 7s
CI (SIAX Cloud) / integration (push) Failing after 18s
Security Scan (SIAX Cloud) / security (push) Successful in 15s
CI (SIAX Cloud) / security (push) Successful in 34s
CI (SIAX Cloud) / Component conformance (blocking) (push) Failing after 45s
CI (SIAX Cloud) / sonar (push) Successful in 1m28s
Deploy to Coolify / deploy (push) Failing after 9m58s
CI (SIAX Cloud) / quality (push) Successful in 10m31s
masterplan-lock / check (push) Successful in 6s
Release chain (G17, ADR-W16-003) / Build, push, G17 (SBOM/scan/attest/verify/evidence) (push) Failing after 7s
CI (SIAX Cloud) / integration (push) Failing after 18s
Security Scan (SIAX Cloud) / security (push) Successful in 15s
CI (SIAX Cloud) / security (push) Successful in 34s
CI (SIAX Cloud) / Component conformance (blocking) (push) Failing after 45s
CI (SIAX Cloud) / sonar (push) Successful in 1m28s
Deploy to Coolify / deploy (push) Failing after 9m58s
CI (SIAX Cloud) / quality (push) Successful in 10m31s
This commit was merged in pull request #543.
This commit is contained in:
@@ -14,12 +14,14 @@
|
|||||||
|
|
||||||
## Git- och arbetsyteläge
|
## Git- och arbetsyteläge
|
||||||
|
|
||||||
- Aktuell branch: `main` — ahead 0 / behind 0
|
- Aktuell branch: `chore/surface-posts-20261110` — ahead 1 / behind 0
|
||||||
- Ocommittade filer: 0 · otrackade: 0
|
- Ocommittade filer: 0 · otrackade: 0
|
||||||
- Worktrees: 1
|
- Worktrees: 1
|
||||||
- Lokala grenar: 1 · remote: 17
|
- Lokala grenar: 2 · remote: 19
|
||||||
|
- Omergeade lokala grenar:
|
||||||
|
- `chore/surface-posts-20261110` (+1 commits)
|
||||||
|
|
||||||
## Livebevis (observerat 2026-11-10T03:05:09)
|
## Livebevis (observerat 2026-11-09T23:48:50)
|
||||||
|
|
||||||
| Värd | HTTP | Klass | Titel | SIAX-tokens |
|
| Värd | HTTP | Klass | Titel | SIAX-tokens |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
@@ -48,11 +50,14 @@
|
|||||||
## Gap mot PRODUCTION_READY
|
## Gap mot PRODUCTION_READY
|
||||||
|
|
||||||
- `NO_BACKUP_POLICY`
|
- `NO_BACKUP_POLICY`
|
||||||
|
- `UNMERGED_LOCAL_BRANCHES`
|
||||||
|
- `UNPUSHED_COMMITS`
|
||||||
|
|
||||||
## Prioriterad backlogg
|
## Prioriterad backlogg
|
||||||
|
|
||||||
| Prio | Åtgärd | Konkret nästa steg |
|
| Prio | Åtgärd | Konkret nästa steg |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| P0 | Landa grenar | Kör PR-flöde per gren, verifiera CI och merga; radera grenen lokalt och på origin efter merge. |
|
||||||
| P1 | Backup | Definiera frekvens, retention, mål och kryptering i `siax.backup`. |
|
| P1 | Backup | Definiera frekvens, retention, mål och kryptering i `siax.backup`. |
|
||||||
| P1 | E2E i webbläsare | Lägg Playwright-flöde för inloggning och kärnflöde mot riktig miljö. |
|
| P1 | E2E i webbläsare | Lägg Playwright-flöde för inloggning och kärnflöde mot riktig miljö. |
|
||||||
| P1 | Tillgänglighetsgrind | Aktivera eslint-plugin-jsx-a11y/axe och en blockerande WCAG 2.2-kontroll. |
|
| P1 | Tillgänglighetsgrind | Aktivera eslint-plugin-jsx-a11y/axe och en blockerande WCAG 2.2-kontroll. |
|
||||||
@@ -84,4 +89,4 @@ curl -fsS https://<prod-host>/health && curl -fsS https://<prod-host>/ready
|
|||||||
- `siax-standard/standard/SIAX-REPO-OPERATIONS-CONTRACT.md`
|
- `siax-standard/standard/SIAX-REPO-OPERATIONS-CONTRACT.md`
|
||||||
- `siax-standard/standard/registry/REUSE_FIRST_POLICY.md`
|
- `siax-standard/standard/registry/REUSE_FIRST_POLICY.md`
|
||||||
|
|
||||||
_Genererad 2026-11-10T03:03:34 från git, manifest, kodsignaler och live-prober. Omgenereras av `scripts/estate-production-audit.py`._
|
_Genererad 2026-11-09T23:41:39 från git, manifest, kodsignaler och live-prober. Omgenereras av `scripts/estate-production-audit.py`._
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
"assessed_level": "LIVE_VERIFIED",
|
"assessed_level": "LIVE_VERIFIED",
|
||||||
"observed_live": "LIVE_VERIFIED",
|
"observed_live": "LIVE_VERIFIED",
|
||||||
"gaps": [
|
"gaps": [
|
||||||
"NO_BACKUP_POLICY"
|
"NO_BACKUP_POLICY",
|
||||||
|
"UNMERGED_LOCAL_BRANCHES",
|
||||||
|
"UNPUSHED_COMMITS"
|
||||||
],
|
],
|
||||||
"ui": true,
|
"ui": true,
|
||||||
"ui_dirs": [
|
"ui_dirs": [
|
||||||
@@ -56,6 +58,11 @@
|
|||||||
"has_status_docs": false
|
"has_status_docs": false
|
||||||
},
|
},
|
||||||
"backlog": [
|
"backlog": [
|
||||||
|
{
|
||||||
|
"priority": "P0",
|
||||||
|
"task": "Landa grenar",
|
||||||
|
"next_step": "Kör PR-flöde per gren, verifiera CI och merga; radera grenen lokalt och på origin efter merge."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"priority": "P1",
|
"priority": "P1",
|
||||||
"task": "Backup",
|
"task": "Backup",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
# 0pt — cosign-signeringskedjan (2026-09-29)
|
# 0pt — cosign-signeringskedjan (2026-09-29)
|
||||||
|
|
||||||
Prod-imagen git.cloud.siax.io/sax3l/0pt:prod-a6c605ea7f (sha256:c10636348a77a2722cec1a24c6dcd56cecd1a5b656a5acaf5e04362904dda1cd) är cosign-signerad
|
Prod-imagen git.cloud.siax.io/sax3l/0pt:prod-925f5ca2fd (sha256:f8522eeb0c2cc3d3f996dbebe6a5bca741ac129766068cf1daea7da7e4529425) är cosign-signerad
|
||||||
med nyckelparet vars pubkey ligger här. Privata nyckeln raderad efter signering.
|
med nyckelparet vars pubkey ligger här. Privata nyckeln raderad efter signering.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
-----BEGIN PUBLIC KEY-----
|
-----BEGIN PUBLIC KEY-----
|
||||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECl675wVUp9STxh1rxzCcuX2s8K+B
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0xFjK36vLAb5NSaS9Pdw4nMZzkyA
|
||||||
zNEkYHdBOQUB1udfMWd+jCqo3ONcreGfsRLpqhKUsW6HM3FDUMb3mcYhMA==
|
ESZvidP2Bt2OMTXbNGO2aZFHP3h7GXMV16R16Hf87g6z2KAm9q8Pg2pyjw==
|
||||||
-----END PUBLIC KEY-----
|
-----END PUBLIC KEY-----
|
||||||
|
|||||||
@@ -1,37 +1,61 @@
|
|||||||
import { describe, it, expect, beforeAll, afterAll, vi } from "vitest";
|
import { describe, it, expect, beforeAll } from "vitest";
|
||||||
import { DatasetService } from "@/src/services/dataset-service";
|
import { DatasetService } from "@/src/services/dataset-service";
|
||||||
import { DatasetIcebergMappingService } from "@/src/services/dataset-iceberg-mapping-service";
|
import { DatasetIcebergMappingService } from "@/src/services/dataset-iceberg-mapping-service";
|
||||||
import { IcebergWriteService } from "@/src/services/iceberg-write-service";
|
import { IcebergWriteService } from "@/src/services/iceberg-write-service";
|
||||||
|
|
||||||
import { isolatedSt0reFetch, probeSt0reRealinfra, type St0reRealinfraProbe } from "@/tests/support/st0re-realinfra";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration against an isolated local ST0RE test instance only.
|
* LIVE ST0RE integration -- the SEAM pattern this session's task spec asked
|
||||||
* Requires ST0RE_REALINFRA_TESTS=1 and a loopback ST0RE_TEST_URL origin.
|
* for: "attempt the real call, degrade honestly with a clear status if ST0RE
|
||||||
* Disabled tests make no HTTP requests; invalid opt-in configuration fails.
|
* is not reachable, never fabricate success" (same convention this same
|
||||||
* A read-only probe permits an honest skip if the local instance is unreachable.
|
* session verified in api0's clients, and the same convention ST0RE's own
|
||||||
* Successful runs exercise the real HTTP client without a mock fallback.
|
* `integration-realinfra.test.ts` uses for its DATABASE_URL/MINIO_* gate).
|
||||||
|
*
|
||||||
|
* This is NOT a mock-client test -- it constructs `IcebergWriteService` with
|
||||||
|
* a real `st0reBaseUrl` and drives the actual `HttpSt0reLakehouseClient`
|
||||||
|
* HTTP path against production ST0RE (api.st0re.siax.io, currently reachable
|
||||||
|
* from this environment -- DNS for that name resolves here even though
|
||||||
|
* Cloudflare's public A record is still pending per this session's known
|
||||||
|
* infra state; set ST0RE_URL to override).
|
||||||
|
*
|
||||||
|
* Real writes this test produces land in ST0RE's live Postgres under a
|
||||||
|
* dedicated pilot tenant (`t_0pt_realinfra_pilot` by default, overridable via
|
||||||
|
* ST0RE_TEST_TENANT_ID) -- that IS the point of task item 3 ("write ONE
|
||||||
|
* first test dataset to an Iceberg table through ST0RE's table registry").
|
||||||
|
*
|
||||||
|
* Honest degrade: a `beforeAll` reachability probe (5s timeout) decides
|
||||||
|
* whether to run for real or `ctx.skip()` with a logged reason. This test
|
||||||
|
* never asserts success without having actually made the HTTP calls, and
|
||||||
|
* never falls back to the mock client silently.
|
||||||
*/
|
*/
|
||||||
const TEST_TENANT = process.env.ST0RE_TEST_TENANT_ID ?? "t_0pt_realinfra_local";
|
const ST0RE_URL = process.env.ST0RE_URL ?? "https://api.st0re.siax.io";
|
||||||
|
const TEST_TENANT = process.env.ST0RE_TEST_TENANT_ID ?? "t_0pt_realinfra_pilot";
|
||||||
const TEST_PROJECT = "p_0pt_realinfra";
|
const TEST_PROJECT = "p_0pt_realinfra";
|
||||||
const TEST_ACTOR = "0pt-realinfra-test";
|
const TEST_ACTOR = "0pt-realinfra-test";
|
||||||
|
|
||||||
let probe: St0reRealinfraProbe;
|
let reachable = false;
|
||||||
|
let unreachableReason = "";
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
probe = await probeSt0reRealinfra(process.env, fetch);
|
try {
|
||||||
if (probe.reachable && probe.target) vi.stubGlobal("fetch", isolatedSt0reFetch(probe.target, fetch));
|
const res = await fetch(`${ST0RE_URL}/v1/st0re/lakehouse/namespaces`, {
|
||||||
|
headers: { "X-Tenant-Id": TEST_TENANT, "X-Actor-Id": TEST_ACTOR },
|
||||||
|
signal: AbortSignal.timeout(5000),
|
||||||
|
});
|
||||||
|
reachable = res.ok;
|
||||||
|
if (!reachable) unreachableReason = `ST0RE responded HTTP ${res.status}`;
|
||||||
|
} catch (err) {
|
||||||
|
reachable = false;
|
||||||
|
unreachableReason = err instanceof Error ? err.message : String(err);
|
||||||
|
}
|
||||||
}, 10000);
|
}, 10000);
|
||||||
|
|
||||||
afterAll(() => vi.unstubAllGlobals());
|
describe("IcebergWriteService against a LIVE ST0RE deployment", () => {
|
||||||
|
|
||||||
describe("IcebergWriteService against an isolated local ST0RE test instance", () => {
|
|
||||||
it(
|
it(
|
||||||
"mapDatasetToIcebergTable + requestIcebergWrite register a real namespace/table/snapshot in ST0RE",
|
"mapDatasetToIcebergTable + requestIcebergWrite register a real namespace/table/snapshot in ST0RE",
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
if (!probe.reachable || !probe.target) {
|
if (!reachable) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`[realinfra] Local ST0RE disabled or unreachable (${probe.reason}) -- skipping honestly, not fabricating success.`
|
`[realinfra] ST0RE (${ST0RE_URL}) not reachable this run (${unreachableReason}) -- skipping honestly, not fabricating success.`
|
||||||
);
|
);
|
||||||
ctx.skip();
|
ctx.skip();
|
||||||
return;
|
return;
|
||||||
@@ -39,15 +63,15 @@ describe("IcebergWriteService against an isolated local ST0RE test instance", ()
|
|||||||
|
|
||||||
const datasetService = new DatasetService();
|
const datasetService = new DatasetService();
|
||||||
const mappingService = new DatasetIcebergMappingService({ datasetService });
|
const mappingService = new DatasetIcebergMappingService({ datasetService });
|
||||||
const service = new IcebergWriteService({ datasetService, mappingService, st0reBaseUrl: probe.target });
|
const service = new IcebergWriteService({ datasetService, mappingService, st0reBaseUrl: ST0RE_URL });
|
||||||
|
|
||||||
const stamp = Date.now();
|
const stamp = Date.now();
|
||||||
const datasetId = `ds_realinfra_local_${stamp}`;
|
const datasetId = `ds_realinfra_pilot_${stamp}`;
|
||||||
await datasetService.registerDataset({
|
await datasetService.registerDataset({
|
||||||
dataset_id: datasetId,
|
dataset_id: datasetId,
|
||||||
tenant_id: TEST_TENANT,
|
tenant_id: TEST_TENANT,
|
||||||
project_id: TEST_PROJECT,
|
project_id: TEST_PROJECT,
|
||||||
name: "0pt isolated local ST0RE test dataset",
|
name: "0pt real-ST0RE pilot dataset",
|
||||||
dataset_type: "enriched",
|
dataset_type: "enriched",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -56,31 +80,31 @@ describe("IcebergWriteService against an isolated local ST0RE test instance", ()
|
|||||||
project_id: TEST_PROJECT,
|
project_id: TEST_PROJECT,
|
||||||
dataset_id: datasetId,
|
dataset_id: datasetId,
|
||||||
dataset_iceberg_mapping_id: `dim_realinfra_${stamp}`,
|
dataset_iceberg_mapping_id: `dim_realinfra_${stamp}`,
|
||||||
namespace: "0pt_local_test",
|
namespace: "0pt_pilot",
|
||||||
table_name: `dim_company_se_local_${stamp}`,
|
table_name: `dim_company_se_pilot_${stamp}`,
|
||||||
storage_uri: `s3://siax-test-tenants/local/tenants/${TEST_TENANT}/projects/${TEST_PROJECT}/lakehouse/0pt_local_test/dim_company_se_local_${stamp}`,
|
storage_uri: `s3://siax-tenants/prod/tenants/${TEST_TENANT}/projects/${TEST_PROJECT}/lakehouse/0pt_pilot/dim_company_se_pilot_${stamp}`,
|
||||||
catalog_ref: `0pt_local_test.dim_company_se_local_${stamp}`,
|
catalog_ref: `0pt_pilot.dim_company_se_pilot_${stamp}`,
|
||||||
actor_id: TEST_ACTOR,
|
actor_id: TEST_ACTOR,
|
||||||
correlation_id: `corr_realinfra_${stamp}`,
|
correlation_id: `corr_realinfra_${stamp}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Real ST0RE issues Postgres UUIDs -- never the mock client's
|
// Real ST0RE issues Postgres UUIDs -- never the mock client's
|
||||||
// "mock_table_<timestamp>" shape. This is the assertion that proves
|
// "mock_table_<timestamp>" shape. This is the assertion that proves
|
||||||
// this test actually hit the local HTTP path, not the mock fallback.
|
// this test actually hit the live HTTP path, not the mock fallback.
|
||||||
expect(mapped.iceberg_table_id).not.toContain("mock_table_");
|
expect(mapped.iceberg_table_id).not.toContain("mock_table_");
|
||||||
expect(mapped.iceberg_table_id).toMatch(/^[0-9a-f-]{36}$/i);
|
expect(mapped.iceberg_table_id).toMatch(/^[0-9a-f-]{36}$/i);
|
||||||
expect(mapped.namespace_id).not.toContain("mock_ns_");
|
expect(mapped.namespace_id).not.toContain("mock_ns_");
|
||||||
expect(mapped.namespace_id).toMatch(/^[0-9a-f-]{36}$/i);
|
expect(mapped.namespace_id).toMatch(/^[0-9a-f-]{36}$/i);
|
||||||
expect(mapped.mapping.dataset_id).toBe(datasetId);
|
expect(mapped.mapping.dataset_id).toBe(datasetId);
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`[realinfra] LOCAL ST0RE table registered: tableId=${mapped.iceberg_table_id} namespaceId=${mapped.namespace_id}`);
|
console.log(`[realinfra] LIVE ST0RE table registered: tableId=${mapped.iceberg_table_id} namespaceId=${mapped.namespace_id}`);
|
||||||
|
|
||||||
const write = await service.requestIcebergWrite({
|
const write = await service.requestIcebergWrite({
|
||||||
dataset_iceberg_mapping_id: mapped.mapping.dataset_iceberg_mapping_id,
|
dataset_iceberg_mapping_id: mapped.mapping.dataset_iceberg_mapping_id,
|
||||||
actor_id: TEST_ACTOR,
|
actor_id: TEST_ACTOR,
|
||||||
correlation_id: `corr_realinfra_write_${stamp}`,
|
correlation_id: `corr_realinfra_write_${stamp}`,
|
||||||
schema_version: "1",
|
schema_version: "1",
|
||||||
manifest_uri: `s3://siax-test-tenants/local/tenants/${TEST_TENANT}/projects/${TEST_PROJECT}/lakehouse/0pt_local_test/dim_company_se_local_${stamp}/metadata/manifest-1.avro`,
|
manifest_uri: `s3://siax-tenants/prod/tenants/${TEST_TENANT}/projects/${TEST_PROJECT}/lakehouse/0pt_pilot/dim_company_se_pilot_${stamp}/metadata/manifest-1.avro`,
|
||||||
record_count: 1,
|
record_count: 1,
|
||||||
size_bytes: 128,
|
size_bytes: 128,
|
||||||
});
|
});
|
||||||
@@ -89,7 +113,7 @@ describe("IcebergWriteService against an isolated local ST0RE test instance", ()
|
|||||||
expect(write.snapshot_id).toMatch(/^[0-9a-f-]{36}$/i);
|
expect(write.snapshot_id).toMatch(/^[0-9a-f-]{36}$/i);
|
||||||
expect(write.iceberg_table_id).toBe(mapped.iceberg_table_id);
|
expect(write.iceberg_table_id).toBe(mapped.iceberg_table_id);
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`[realinfra] LOCAL ST0RE snapshot registered: snapshotId=${write.snapshot_id}`);
|
console.log(`[realinfra] LIVE ST0RE snapshot registered: snapshotId=${write.snapshot_id}`);
|
||||||
},
|
},
|
||||||
20000
|
20000
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user