492 lines
13 KiB
TypeScript
492 lines
13 KiB
TypeScript
/**
|
|
* Deterministic fixture dataset for the mocked query service.
|
|
* Object types use the report-stream vocabulary (manifest / certificate / aspa).
|
|
*/
|
|
|
|
export const RUN_2 = {
|
|
schemaVersion: 1,
|
|
runId: "run_0002",
|
|
runSeq: 2,
|
|
validationTime: "2026-07-16T23:55:00Z",
|
|
syncMode: "delta",
|
|
wallMs: 732000,
|
|
artifactPaths: {
|
|
"report.json": "/data/runs/run_0002/report.json",
|
|
"run-summary.json": "/data/runs/run_0002/run-summary.json",
|
|
},
|
|
counts: {
|
|
publicationPoints: 4,
|
|
objects: 1284,
|
|
rejectedObjects: 2,
|
|
warnings: 3,
|
|
trustAnchors: 5,
|
|
vrps: 987,
|
|
aspas: 12,
|
|
},
|
|
indexStatus: "ready",
|
|
};
|
|
|
|
export const RUN_1 = {
|
|
...RUN_2,
|
|
runId: "run_0001",
|
|
runSeq: 1,
|
|
validationTime: "2026-07-15T23:50:00Z",
|
|
syncMode: "snapshot",
|
|
wallMs: 1290000,
|
|
artifactPaths: {
|
|
"report.json": "/data/runs/run_0001/report.json",
|
|
"run-summary.json": "/data/runs/run_0001/run-summary.json",
|
|
},
|
|
counts: { ...RUN_2.counts, objects: 1270, vrps: 981 },
|
|
};
|
|
|
|
export const RUNS = [RUN_2, RUN_1];
|
|
|
|
export const REPO_A = {
|
|
repoId: "repo-a1b2c3d4e5f6",
|
|
uri: "rsync://repo-a.example/ca1/",
|
|
host: "repo-a.example",
|
|
transport: "rrdp",
|
|
publicationPoints: 2,
|
|
objects: 900,
|
|
rejectedObjects: 1,
|
|
downloadBytes: 245_000_000,
|
|
syncDurationMsTotal: 12_400,
|
|
phases: { rrdp_snapshot: 1, rrdp_delta: 1 },
|
|
terminalStates: { fresh: 2 },
|
|
};
|
|
|
|
export const REPO_B = {
|
|
repoId: "repo-b2c3d4e5f6a7",
|
|
uri: "rsync://repo-b.example/ca2/",
|
|
host: "repo-b.example",
|
|
transport: "rsync",
|
|
publicationPoints: 1,
|
|
objects: 300,
|
|
rejectedObjects: 1,
|
|
downloadBytes: 80_000_000,
|
|
syncDurationMsTotal: 45_800,
|
|
phases: { rsync: 1 },
|
|
terminalStates: { cached: 1 },
|
|
};
|
|
|
|
export const REPO_C = {
|
|
repoId: "repo-c3d4e5f6a7b8",
|
|
uri: "rsync://repo-c.example/ca3/",
|
|
host: "repo-c.example",
|
|
transport: "rrdp",
|
|
publicationPoints: 1,
|
|
objects: 84,
|
|
rejectedObjects: 0,
|
|
downloadBytes: 9_000_000,
|
|
syncDurationMsTotal: 3_100,
|
|
phases: { rrdp_delta: 1 },
|
|
terminalStates: { fresh: 1 },
|
|
};
|
|
|
|
export const REPOS = [REPO_A, REPO_B, REPO_C];
|
|
|
|
export const PP_1 = {
|
|
ppId: "node_1",
|
|
repoId: REPO_A.repoId,
|
|
nodeId: 1,
|
|
rsyncBaseUri: "rsync://repo-a.example/ca1/",
|
|
manifestRsyncUri: "rsync://repo-a.example/ca1/manifest.mft",
|
|
publicationPointRsyncUri: "rsync://repo-a.example/ca1/",
|
|
rrdpNotificationUri: "https://repo-a.example/notification.xml",
|
|
source: "rrdp",
|
|
repoSyncSource: "rrdp",
|
|
repoSyncPhase: "rrdp_delta",
|
|
repoSyncDurationMs: 1200,
|
|
repoSyncError: null,
|
|
repoTerminalState: "fresh",
|
|
thisUpdate: "2026-07-16T23:00:00Z",
|
|
nextUpdate: "2026-07-17T23:00:00Z",
|
|
objects: 610,
|
|
rejectedObjects: 1,
|
|
warnings: 2,
|
|
};
|
|
|
|
export const PP_2 = {
|
|
...PP_1,
|
|
ppId: "node_2",
|
|
nodeId: 2,
|
|
manifestRsyncUri: "rsync://repo-a.example/ca1b/manifest.mft",
|
|
publicationPointRsyncUri: "rsync://repo-a.example/ca1b/",
|
|
objects: 290,
|
|
rejectedObjects: 0,
|
|
warnings: 1,
|
|
};
|
|
|
|
export const PP_3 = {
|
|
...PP_1,
|
|
ppId: "node_3",
|
|
nodeId: 3,
|
|
repoId: REPO_B.repoId,
|
|
manifestRsyncUri: "rsync://repo-b.example/ca2/manifest.mft",
|
|
publicationPointRsyncUri: "rsync://repo-b.example/ca2/",
|
|
rrdpNotificationUri: null,
|
|
source: "rsync",
|
|
repoSyncSource: "rsync",
|
|
repoSyncPhase: "rsync",
|
|
repoTerminalState: "cached",
|
|
objects: 300,
|
|
rejectedObjects: 1,
|
|
warnings: 0,
|
|
};
|
|
|
|
export const PPS = [PP_1, PP_2, PP_3];
|
|
|
|
const SHA = (ch: string) => ch.repeat(64);
|
|
|
|
export const OBJ_ROA = {
|
|
objectInstanceId: "obj-roa-0001",
|
|
uri: "rsync://repo-a.example/ca1/alice.roa",
|
|
sha256: SHA("a"),
|
|
objectType: "roa",
|
|
result: "ok",
|
|
detailSummary: null,
|
|
repoId: REPO_A.repoId,
|
|
ppId: PP_1.ppId,
|
|
sourceSection: "fresh",
|
|
rejected: false,
|
|
rejectReason: null,
|
|
};
|
|
|
|
export const OBJ_MFT = {
|
|
objectInstanceId: "obj-mft-0001",
|
|
uri: "rsync://repo-a.example/ca1/manifest.mft",
|
|
sha256: SHA("b"),
|
|
objectType: "manifest",
|
|
result: "ok",
|
|
detailSummary: null,
|
|
repoId: REPO_A.repoId,
|
|
ppId: PP_1.ppId,
|
|
sourceSection: "fresh",
|
|
rejected: false,
|
|
rejectReason: null,
|
|
};
|
|
|
|
export const OBJ_CER_REJECTED = {
|
|
objectInstanceId: "obj-cer-0001",
|
|
uri: "rsync://repo-a.example/ca1/stale.cer",
|
|
sha256: SHA("c"),
|
|
objectType: "certificate",
|
|
result: "error",
|
|
detailSummary: "certificate expired: notAfter 2026-01-01T00:00:00Z",
|
|
repoId: REPO_A.repoId,
|
|
ppId: PP_1.ppId,
|
|
sourceSection: "cached",
|
|
rejected: true,
|
|
rejectReason: "certificate expired: notAfter 2026-01-01T00:00:00Z",
|
|
};
|
|
|
|
export const OBJ_ASPA = {
|
|
objectInstanceId: "obj-asa-0001",
|
|
uri: "rsync://repo-b.example/ca2/bob.asa",
|
|
sha256: SHA("d"),
|
|
objectType: "aspa",
|
|
result: "ok",
|
|
detailSummary: null,
|
|
repoId: REPO_B.repoId,
|
|
ppId: PP_3.ppId,
|
|
sourceSection: "cached",
|
|
rejected: false,
|
|
rejectReason: null,
|
|
};
|
|
|
|
export const OBJ_ROA_REJECTED = {
|
|
objectInstanceId: "obj-roa-0002",
|
|
uri: "rsync://repo-b.example/ca2/broken.roa",
|
|
sha256: SHA("e"),
|
|
objectType: "roa",
|
|
result: "error",
|
|
detailSummary: "manifest stale: thisUpdate in the past",
|
|
repoId: REPO_B.repoId,
|
|
ppId: PP_3.ppId,
|
|
sourceSection: "cached",
|
|
rejected: true,
|
|
rejectReason: "manifest stale: thisUpdate in the past",
|
|
};
|
|
|
|
export const OBJ_CRL = {
|
|
objectInstanceId: "obj-crl-0001",
|
|
uri: "rsync://repo-a.example/ca1/main.crl",
|
|
sha256: SHA("f"),
|
|
objectType: "crl",
|
|
result: "ok",
|
|
detailSummary: null,
|
|
repoId: REPO_A.repoId,
|
|
ppId: PP_1.ppId,
|
|
sourceSection: "fresh",
|
|
rejected: false,
|
|
rejectReason: null,
|
|
};
|
|
|
|
export const OBJECTS = [OBJ_ROA, OBJ_MFT, OBJ_CER_REJECTED, OBJ_ASPA, OBJ_ROA_REJECTED, OBJ_CRL];
|
|
|
|
export const STATS_VALIDATION = { ok: 1279, error: 2, skipped: 3 };
|
|
export const STATS_OBJECT_TYPES = {
|
|
roa: 640,
|
|
manifest: 4,
|
|
crl: 4,
|
|
certificate: 620,
|
|
aspa: 12,
|
|
gbr: 4,
|
|
};
|
|
export const STATS_REASONS = {
|
|
"certificate expired: notAfter 2026-01-01T00:00:00Z": 1,
|
|
"manifest stale: thisUpdate in the past": 1,
|
|
};
|
|
|
|
export const ROA_PROJECTION = {
|
|
schemaVersion: 2,
|
|
sha256: SHA("a"),
|
|
objectType: "roa",
|
|
parseStatus: "ok",
|
|
// Mirrors the live query service shape:
|
|
// projection = { input, object: { type, roa|manifest|… }, schemaVersion, tool }
|
|
projection: {
|
|
input: {
|
|
type: "roa",
|
|
path: "rsync://repo-a.example/ca1/alice.roa",
|
|
bytes: { len: 1280, sha256: SHA("a") },
|
|
},
|
|
object: {
|
|
type: "roa",
|
|
roa: {
|
|
asId: 65001,
|
|
ipAddressFamilies: [
|
|
{
|
|
afi: "ipv4",
|
|
addresses: [
|
|
{ prefix: "203.0.113.0/24", maxLength: 24 },
|
|
{ prefix: "198.51.100.0/25", maxLength: 25 },
|
|
],
|
|
},
|
|
{
|
|
afi: "ipv6",
|
|
addresses: [{ prefix: "2001:db8::/32", maxLength: 48 }],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
schemaVersion: 2,
|
|
tool: "rpki",
|
|
},
|
|
};
|
|
|
|
export const MFT_PROJECTION = {
|
|
schemaVersion: 2,
|
|
sha256: SHA("b"),
|
|
objectType: "mft",
|
|
parseStatus: "ok",
|
|
projection: {
|
|
input: {
|
|
type: "mft",
|
|
path: "rsync://repo-a.example/ca1/manifest.mft",
|
|
bytes: { len: 2048, sha256: SHA("b") },
|
|
},
|
|
object: {
|
|
type: "mft",
|
|
manifest: {
|
|
manifestNumberHex: "0A2F",
|
|
thisUpdate: "2026-07-16T23:00:00Z",
|
|
nextUpdate: "2026-07-17T23:00:00Z",
|
|
fileHashAlg: "sha256",
|
|
fileCount: 3,
|
|
},
|
|
},
|
|
schemaVersion: 2,
|
|
tool: "rpki",
|
|
},
|
|
};
|
|
|
|
export const MFT_FILES = [
|
|
{ fileName: "alice.roa", hashHex: SHA("a") },
|
|
{ fileName: "manifest.mft", hashHex: SHA("b") },
|
|
{ fileName: "stale.cer", hashHex: SHA("c") },
|
|
];
|
|
|
|
// Certificate projection in the real nested API shape:
|
|
// certificate payload under `object.resourceCertificate`, SKI/AKI/SIA/AIA/CRLDP
|
|
// and IP/AS resources under `extensions`.
|
|
export const CER_PROJECTION = {
|
|
schemaVersion: 2,
|
|
sha256: SHA("c"),
|
|
objectType: "cer",
|
|
parseStatus: "ok",
|
|
projection: {
|
|
input: {
|
|
type: "cer",
|
|
path: "rsync://repo-a.example/ca1/stale.cer",
|
|
bytes: { len: 1534, sha256: SHA("c") },
|
|
},
|
|
object: {
|
|
type: "cer",
|
|
decode: { profileValid: true },
|
|
resourceCertificate: {
|
|
kind: "Ca",
|
|
version: 3,
|
|
serialNumberHex: "02C6C7",
|
|
issuer: "CN=A90DC5BE, serialNumber=0E65A4F5",
|
|
subject: "CN=A9114E750000, serialNumber=5A179648",
|
|
validity: { notBefore: "2026-07-23T00:30:06Z", notAfter: "2027-09-30T00:00:00Z" },
|
|
signatureAlgorithm: "1.2.840.113549.1.1.11",
|
|
extensions: {
|
|
subjectKeyIdentifier: "5a179648b3ef2369dce7bdb58140ff7dc7060abf",
|
|
authorityKeyIdentifier: "0e65a4f5fd36b5bd68eb3c923408978c907aa79f",
|
|
basicConstraintsCa: true,
|
|
subjectInfoAccess: {
|
|
accessDescriptions: [
|
|
{ accessMethodOid: "1.3.6.1.5.5.7.48.5", accessLocation: "rsync://repo-a.example/ca1/" },
|
|
],
|
|
},
|
|
caIssuersUris: ["rsync://repo-a.example/ca1/issuer.cer"],
|
|
crlDistributionPointsUris: ["rsync://repo-a.example/ca1/main.crl"],
|
|
ipResources: {
|
|
families: [
|
|
{
|
|
afi: "Ipv4",
|
|
choice: {
|
|
AddressesOrRanges: [
|
|
{ Prefix: { addr: [103, 152, 34, 0], afi: "Ipv4", prefix_len: 23 } },
|
|
{ Range: { min: { addr: [192, 0, 2, 0] }, max: { addr: [192, 0, 2, 255] } } },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
afi: "Ipv6",
|
|
choice: {
|
|
AddressesOrRanges: [
|
|
{
|
|
Prefix: {
|
|
addr: [38, 6, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
afi: "Ipv6",
|
|
prefix_len: 32,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
asResources: {
|
|
asnum: {
|
|
AsIdsOrRanges: [{ Id: 38008 }, { Id: 38023 }, { Range: { min: 65536, max: 65551 } }],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
schemaVersion: 2,
|
|
tool: "rpki",
|
|
},
|
|
};
|
|
|
|
// CRL projection in the real nested API shape: CRL fields sit directly on the
|
|
// typed payload (no `crl` wrapper); crlNumber/AKI live under `extensions`.
|
|
export const CRL_PROJECTION = {
|
|
schemaVersion: 2,
|
|
sha256: SHA("f"),
|
|
objectType: "crl",
|
|
parseStatus: "ok",
|
|
projection: {
|
|
input: {
|
|
type: "crl",
|
|
path: "rsync://repo-a.example/ca1/main.crl",
|
|
bytes: { len: 900, sha256: SHA("f") },
|
|
},
|
|
object: {
|
|
type: "crl",
|
|
decode: { profileValid: true },
|
|
issuer: "CN=A9114E750000, serialNumber=5A179648",
|
|
thisUpdate: "2026-07-23T02:47:00Z",
|
|
nextUpdate: "2026-07-24T02:52:00Z",
|
|
signatureAlgorithm: "1.2.840.113549.1.1.11",
|
|
extensions: {
|
|
authorityKeyIdentifier: "5a179648b3ef2369dce7bdb58140ff7dc7060abf",
|
|
crlNumber: 3394,
|
|
crlNumberHex: "0D42",
|
|
},
|
|
revokedCertificates: {
|
|
count: 2,
|
|
entries: [
|
|
{ serialNumberHex: "1B0B0AD86D78E77D1491B5069E6287D08EEA7C17", revocationDate: "2027-02-13T13:22:01Z" },
|
|
{ serialNumberHex: "6A106263F88133615B7E8D3466C192CEC0904F2D", revocationDate: "2027-03-18T19:58:00Z" },
|
|
],
|
|
},
|
|
},
|
|
schemaVersion: 2,
|
|
tool: "rpki",
|
|
},
|
|
};
|
|
|
|
export const CRL_REVOKED = [
|
|
{ serialNumberHex: "1B0B0AD86D78E77D1491B5069E6287D08EEA7C17", revocationDate: "2027-02-13T13:22:01Z" },
|
|
{ serialNumberHex: "6A106263F88133615B7E8D3466C192CEC0904F2D", revocationDate: "2027-03-18T19:58:00Z" },
|
|
];
|
|
|
|
export const VALIDATION_SUMMARY = {
|
|
finalStatus: "valid",
|
|
auditResult: "ok",
|
|
detailSummary: null,
|
|
parsevalidate: { status: "ok", issues: [] },
|
|
chainvalidate: { status: "ok", issues: [] },
|
|
};
|
|
|
|
export const EXPLAIN_RECORD = {
|
|
finalStatus: "valid",
|
|
auditResult: "ok",
|
|
authoritative: false,
|
|
explainMode: "audit_projection",
|
|
parsevalidate: { status: "ok", issues: [] },
|
|
chainvalidate: { status: "ok", mode: "audit_projection", issues: [], edgesCount: 2 },
|
|
chainEdges: [],
|
|
};
|
|
|
|
export const CHAIN_EDGES = [
|
|
{
|
|
relation: "issued_by",
|
|
fromUri: "rsync://repo-a.example/ca1/alice.roa",
|
|
toUri: "rsync://repo-a.example/ca1/ca-certificate.cer",
|
|
toObjectInstanceId: "obj-cer-0002",
|
|
toSha256: SHA("f"),
|
|
status: "linked",
|
|
},
|
|
{
|
|
relation: "listed_in",
|
|
fromUri: "rsync://repo-a.example/ca1/alice.roa",
|
|
toUri: "rsync://repo-a.example/ca1/manifest.mft",
|
|
toObjectInstanceId: "obj-mft-0001",
|
|
toSha256: SHA("b"),
|
|
status: "linked",
|
|
},
|
|
];
|
|
|
|
export const HEALTH = {
|
|
status: "ok",
|
|
service: "rpki_query_service",
|
|
version: 1,
|
|
latestReadyRun: "run_0002",
|
|
};
|
|
|
|
export const SERVICE_INFO = { service: "rpki_query_service", version: 1 };
|
|
|
|
/**
|
|
* VRP lookup fixtures (backend feature #122). 61 rows match `ip=81.68.1.1`
|
|
* so the UI's 50-row page size paginates; the /16 row exercises covering
|
|
* semantics for prefix queries, the IPv6 row exercises the second family.
|
|
*/
|
|
export const VRPS = [
|
|
{ runId: "run_0002", asn: 45090, prefix: "81.68.0.0/14", maxLength: 14 },
|
|
{ runId: "run_0002", asn: 64496, prefix: "81.68.0.0/16", maxLength: 24 },
|
|
...Array.from({ length: 59 }, (_, i) => ({
|
|
runId: "run_0002",
|
|
asn: 64512 + i,
|
|
prefix: "81.68.0.0/14",
|
|
maxLength: 14,
|
|
})),
|
|
{ runId: "run_0002", asn: 0, prefix: "2001:7fa:0:1::/64", maxLength: 64 },
|
|
];
|