#!/usr/bin/env node

import { createPublicKey, verify as verifySignature } from 'node:crypto'
import { readFileSync, realpathSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { canonical, exact, parseJsonStrict, sha256, verifyPacket } from './verify-packet.mjs'

const PROFILE = 'bulla.complete-effect-mediation/0.1-experimental'
const REPORT_PROFILE = 'bulla.complete-effect-mediation-report/0.1-experimental'
const RECEIVER = 'effect-lock-receiver-01'
const COUNTERPARTY = 'effect-lock-counterparty-01'
const TARGET = 'durable-object://locked-synthetic-receiver/sandbox.append'
const EFFECT = 'sandbox.append'
const HASH = /^sha256:[0-9a-f]{64}$/u
const TIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u
const RECEIPT_FIELDS = [
  'action', 'anchor_ref', 'authorization', 'canonicalization', 'claimed_at', 'conventions',
  'diagnostic_ref', 'event_id', 'evidence_refs', 'hashes', 'kind', 'mandate', 'occurrence',
  'producer', 'remedy', 'retention', 'schema_version', 'signature', 'stake',
]
const PROOF_FIELDS = ['issuer', 'proofValue', 'purpose', 'type', 'verificationMethod']
const RESIDUAL_BOUNDARY = [
  'CLOUD_OR_PLATFORM_ADMINISTRATOR_CONTAINMENT_NOT_ESTABLISHED',
  'ABSENCE_OF_COPIED_RECEIVER_CREDENTIALS_NOT_ESTABLISHED',
  'SOURCE_OR_DEPLOYMENT_IMMUTABILITY_NOT_ESTABLISHED',
  'WORLDLY_TRUTH_OR_POLICY_CORRECTNESS_NOT_ESTABLISHED',
  'PROVIDER_EXECUTION_BINDING_NOT_ESTABLISHED',
  'UNDISCLOSED_EXTERNAL_EFFECTS_NOT_ESTABLISHED',
  'PRODUCTION_SAFETY_OR_LEGAL_EFFECT_NOT_ESTABLISHED',
]

const EVIDENCE_POLICY = {
  profile: 'bulla.complete-effect-mediation-policy/0.1-experimental',
  required_actions: ['eval.run.authorize', 'boundary.decision'],
  required_decision: 'PERMIT',
  effect_class: EFFECT,
  use_limit: 1,
}
const VERIFIER_DEFINITION = {
  profile: 'bulla.complete-effect-mediation-verifier/0.1-experimental',
  canonicalization: 'bulla-jcs-int/1',
  receipt_schema: '0.4',
  target_verifies: true,
}
const GRAPH = {
  profile: 'bulla.complete-effect-mediation-runtime-graph/0.1-experimental',
  protected_node: 'protected_append_commit',
  nodes: [
    'grant_issue', 'redemption_receive', 'target_verify', 'grant_consume',
    'protected_append_commit', 'effect_record_persist', 'state_read', 'effect_read',
  ],
  transitions: [
    ['grant_issue', 'redemption_receive'],
    ['redemption_receive', 'target_verify'],
    ['target_verify', 'grant_consume'],
    ['grant_consume', 'protected_append_commit'],
    ['protected_append_commit', 'effect_record_persist'],
  ],
  public_routes: {
    'POST /grants': 'grant_issue',
    'POST /redemptions': 'redemption_receive',
    'GET /state': 'state_read',
    'GET /effect': 'effect_read',
  },
}

function json(root, path) {
  return parseJsonStrict(readFileSync(join(root, path)), path)
}

function requireHash(value, label) {
  if (typeof value !== 'string' || !HASH.test(value)) throw new Error(`${label} is not a canonical hash`)
  return value
}

function decodeBase58(value) {
  const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
  let number = 0n
  for (const character of value) {
    const digit = alphabet.indexOf(character)
    if (digit < 0) throw new Error('invalid base58btc DID')
    number = number * 58n + BigInt(digit)
  }
  const bytes = []
  while (number > 0n) { bytes.push(Number(number & 255n)); number >>= 8n }
  bytes.reverse()
  for (const character of value) { if (character === '1') bytes.unshift(0); else break }
  return Buffer.from(bytes)
}

function publicKey(did) {
  if (typeof did !== 'string' || !did.startsWith('did:key:z')) throw new Error('receipt issuer is not did:key')
  const decoded = decodeBase58(did.slice('did:key:z'.length))
  if (decoded.length !== 34 || decoded[0] !== 0xed || decoded[1] !== 0x01) throw new Error('receipt issuer is not Ed25519 did:key')
  return createPublicKey({
    key: Buffer.concat([Buffer.from('302a300506032b6570032100', 'hex'), decoded.subarray(2)]),
    format: 'der',
    type: 'spki',
  })
}

function proofPreimage(purpose, digest) {
  return Buffer.from(canonical({ context: 'bulla-proof', schema: '0.4', purpose, digest }))
}

function verifyProof(proof, issuer, purpose, digest) {
  exact(proof, PROOF_FIELDS, `${purpose} proof`)
  if (proof.type !== 'bulla/ed25519-2026' || proof.purpose !== purpose || proof.issuer !== issuer || proof.verificationMethod !== issuer) throw new Error(`${purpose} proof fields are not accepted`)
  if (typeof proof.proofValue !== 'string' || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(proof.proofValue)) throw new Error(`${purpose} proof is not canonical base64`)
  const signature = Buffer.from(proof.proofValue, 'base64')
  if (signature.toString('base64') !== proof.proofValue || !verifySignature(null, proofPreimage(purpose, digest), publicKey(issuer), signature)) throw new Error(`${purpose} proof failed`)
}

function verifyReceipt(receipt, expectedIssuer, actionType, subjectFields, label) {
  exact(receipt, RECEIPT_FIELDS, label)
  exact(receipt.action, ['subject', 'type'], `${label}.action`)
  exact(receipt.action.subject, subjectFields, `${label}.action.subject`)
  exact(receipt.hashes, ['attestation', 'content', 'event', 'log_leaf'], `${label}.hashes`)
  exact(receipt.producer, ['bulla_version', 'issuer_role', 'profile'], `${label}.producer`)
  exact(receipt.diagnostic_ref, ['status'], `${label}.diagnostic_ref`)
  exact(receipt.anchor_ref, [], `${label}.anchor_ref`)
  exact(receipt.mandate, ['authority', 'bounds'], `${label}.mandate`)
  exact(receipt.mandate.authority, ['delegation', 'policy', 'principal'], `${label}.mandate.authority`)
  exact(receipt.mandate.bounds, ['scope'], `${label}.mandate.bounds`)
  exact(receipt.remedy, ['challenge_window', 'forum', 'remedies'], `${label}.remedy`)
  exact(receipt.remedy.forum, ['log_endpoint', 'trusted_root_ref'], `${label}.remedy.forum`)
  exact(receipt.retention, ['disclosure', 'record'], `${label}.retention`)
  if (!Array.isArray(receipt.evidence_refs) || receipt.evidence_refs.some((entry) => {
    exact(entry, ['grounding', 'hash', 'name'], `${label} evidence reference`)
    return typeof entry.name !== 'string' || entry.name.length === 0 || !HASH.test(entry.hash) || !['self_asserted', 'counterparty_signed', 'execution_verified'].includes(entry.grounding)
  })) throw new Error(`${label} evidence references are not accepted`)
  if (!TIME.test(receipt.claimed_at) || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(receipt.event_id)) throw new Error(`${label} event binding is not canonical`)
  if (!Array.isArray(receipt.remedy.remedies) || receipt.remedy.remedies.length !== 1) throw new Error(`${label} remedy is not closed`)
  exact(receipt.remedy.remedies[0], ['anchor', 'rung', 'verifier'], `${label} remedy item`)
  if (receipt.schema_version !== '0.4' || receipt.canonicalization !== 'bulla-jcs-int/1' || receipt.kind !== 'action_receipt' || receipt.action.type !== actionType || receipt.stake !== null || receipt.diagnostic_ref.status !== 'not_applicable' || !Array.isArray(receipt.conventions) || receipt.conventions.length !== 0) throw new Error(`${label} envelope is not accepted`)
  if (receipt.producer.bulla_version !== 'source' || receipt.producer.profile !== 'bulla.control-plane-alpha/0.1-experimental' || receipt.producer.issuer_role !== receipt.action.subject.issuer_role || receipt.mandate.authority.principal !== expectedIssuer || !Array.isArray(receipt.mandate.authority.delegation) || receipt.mandate.authority.delegation.length !== 0) throw new Error(`${label} authority is not accepted`)
  if (receipt.signature.issuer !== expectedIssuer) throw new Error(`${label} issuer is not pinned`)
  const contentPreimage = {
    schema_version: '0.4', canonicalization: 'bulla-jcs-int/1', kind: 'action_receipt',
    action: receipt.action, diagnostic_ref: receipt.diagnostic_ref,
    evidence_refs: receipt.evidence_refs, anchor_ref: receipt.anchor_ref,
  }
  const content = sha256(Buffer.from(canonical(contentPreimage)))
  const event = sha256(Buffer.from(canonical({ content_hash: content, event_id: receipt.event_id, claimed_at: receipt.claimed_at })))
  const envelope = {
    deed_schema: '0.2', authority: receipt.mandate.authority, bounds: receipt.mandate.bounds,
    recourse: receipt.remedy, retention_class: receipt.retention.record,
    disclosure_class: receipt.retention.disclosure,
  }
  const envelopeHash = sha256(Buffer.from(canonical(envelope)))
  const authorizationHash = sha256(Buffer.from(canonical({ event_hash: event, envelope_hash: envelopeHash })))
  verifyProof(receipt.signature, expectedIssuer, 'content', content)
  verifyProof(receipt.occurrence, expectedIssuer, 'occurrence', event)
  verifyProof(receipt.authorization, expectedIssuer, 'authorization', authorizationHash)
  const attestation = sha256(Buffer.from(canonical({
    content_hash: content, signature: receipt.signature, event_hash: event,
    occurrence: receipt.occurrence, recourse_envelope: envelope, authorization: receipt.authorization,
  })))
  const leaf = sha256(Buffer.concat([Buffer.from([0]), Buffer.from(attestation)]))
  if (receipt.hashes.content !== content || receipt.hashes.event !== event || receipt.hashes.attestation !== attestation || receipt.hashes.log_leaf !== leaf) throw new Error(`${label} hashes do not recompute`)
  return receipt.action.subject
}

function sourceRoot(root, closure, key) {
  const section = exact(closure[key], ['root', 'members'], `source closure ${key}`)
  if (!Array.isArray(section.members)) throw new Error(`source closure ${key} members are not an array`)
  const members = section.members.map((member, index) => {
    exact(member, ['path', 'byte_length', 'sha256'], `${key} source member ${index}`)
    if (typeof member.path !== 'string' || !member.path.startsWith(`source/${key}/`) || member.path.includes('..') || member.path.includes('\\')) throw new Error(`${key} source member path escapes its jurisdiction`)
    const bytes = readFileSync(join(root, member.path))
    if (bytes.length !== member.byte_length || sha256(bytes) !== member.sha256) throw new Error(`${key} source member changed: ${member.path}`)
    if (index > 0 && section.members[index - 1].path >= member.path) throw new Error(`${key} source members are not ordered`)
    return member
  })
  const computed = sha256(Buffer.from(canonical({ profile: `bulla.effect-lock-${key}-source/0.1`, members })))
  if (computed !== section.root) throw new Error(`${key} source root does not recompute`)
  return computed
}

function graphResult(graph) {
  if (canonical(graph) !== canonical(GRAPH)) throw new Error('declared graph is not the accepted graph')
  const adjacency = new Map(GRAPH.nodes.map((node) => [node, []]))
  for (const [from, to] of GRAPH.transitions) adjacency.get(from).push(to)
  const visit = (node, path = []) => {
    if (path.includes(node)) throw new Error('declared graph contains a cycle')
    const next = [...path, node]
    if (node === GRAPH.protected_node) return [next]
    return adjacency.get(node).flatMap((child) => visit(child, next))
  }
  const paths = ['grant_issue', 'redemption_receive'].flatMap((entry) => visit(entry))
  if (paths.length === 0 || paths.some((path) => !(path.indexOf('target_verify') >= 0 && path.indexOf('target_verify') < path.indexOf('grant_consume') && path.indexOf('grant_consume') < path.indexOf('protected_append_commit')))) throw new Error('declared graph admits an unmediated mutation path')
  return {
    result: 'ESTABLISHED_IN_DECLARED_GRAPH',
    protected_node: GRAPH.protected_node,
    incoming: ['grant_consume'],
    graph_root: sha256(Buffer.from(canonical(GRAPH))),
  }
}

export function computeReport(packetRoot) {
  const verified = verifyPacket(packetRoot)
  const root = verified.root
  const accepted = exact(json(root, 'accepted-context.json'), [
    'profile', 'receiver_issuer', 'authorization_issuer', 'boundary_issuer',
    'evidence_policy_hash', 'verifier_hash', 'runtime_graph_root', 'role_set_hash',
    'semantic_epoch', 'authority_epoch',
  ], 'accepted context')
  if (accepted.profile !== PROFILE || new Set([accepted.receiver_issuer, accepted.authorization_issuer, accepted.boundary_issuer]).size !== 3) throw new Error('accepted context role topology is invalid')
  const roles = { receiver: accepted.receiver_issuer, authorization: accepted.authorization_issuer, boundary: accepted.boundary_issuer }
  const roleSetHash = sha256(Buffer.from(canonical({ profile: 'bulla.effect-lock-role-set/0.1-experimental', roles })))
  const graph = graphResult(json(root, 'declared-runtime-graph.json'))
  const policyHash = sha256(Buffer.from(canonical(EVIDENCE_POLICY)))
  const verifierHash = sha256(Buffer.from(canonical({ definition: VERIFIER_DEFINITION, runtime_graph_root: graph.graph_root })))
  const authorityEpoch = sha256(Buffer.from(canonical({ profile: 'bulla.effect-lock-authority-epoch/1', role_set_hash: roleSetHash })))
  if (accepted.role_set_hash !== roleSetHash || accepted.runtime_graph_root !== graph.graph_root || accepted.evidence_policy_hash !== policyHash || accepted.verifier_hash !== verifierHash || accepted.authority_epoch !== authorityEpoch) throw new Error('accepted context does not recompute')

  const redemption = exact(json(root, 'redemption.json'), [
    'profile', 'grant', 'mandate', 'boundary_decision', 'authzen_request',
    'authzen_response', 'effect_arguments', 'receiver_nonce', 'evidence_bundle_root',
  ], 'redemption')
  if (redemption.profile !== 'bulla.effect-redemption/0.1-experimental') throw new Error('redemption profile is not accepted')
  if (canonical(json(root, 'grant.json')) !== canonical(redemption.grant)) throw new Error('standalone grant disagrees with the redeemed grant')
  const grantFields = [
    'profile', 'grant_id', 'run_id', 'receiver_id', 'counterparty_id', 'target', 'effect_class',
    'arguments_hash', 'receiver_nonce', 'evidence_policy_hash', 'verifier_hash', 'runtime_graph_root',
    'role_set_hash', 'semantic_epoch', 'authority_epoch', 'valid_from', 'valid_until', 'use_limit', 'issuer_role',
  ]
  const commonFields = ['profile', 'mandate_id', 'run_id', 'receiver_id', 'counterparty_id', 'target', 'effect_class', 'arguments_hash', 'valid_from', 'valid_until', 'issuer_role']
  const decisionFields = ['profile', 'decision', 'run_id', 'receiver_id', 'counterparty_id', 'target', 'effect_class', 'arguments_hash', 'receiver_nonce', 'request_hash', 'response_hash', 'evidence_policy_hash', 'semantic_epoch', 'authority_epoch', 'issuer_role']
  const grant = verifyReceipt(redemption.grant, accepted.receiver_issuer, 'effect.grant.issue', grantFields, 'grant')
  const mandate = verifyReceipt(redemption.mandate, accepted.authorization_issuer, 'eval.run.authorize', commonFields, 'mandate')
  const decision = verifyReceipt(redemption.boundary_decision, accepted.boundary_issuer, 'boundary.decision', decisionFields, 'boundary decision')
  if (redemption.grant.evidence_refs.length !== 0 || redemption.mandate.evidence_refs.length !== 0 || canonical(redemption.boundary_decision.evidence_refs) !== canonical([
    { name: 'mandate', hash: redemption.mandate.hashes.attestation, grounding: 'counterparty_signed' },
    { name: 'authzen-request', hash: sha256(Buffer.from(canonical(redemption.authzen_request))), grounding: 'self_asserted' },
    { name: 'authzen-response', hash: sha256(Buffer.from(canonical(redemption.authzen_response))), grounding: 'self_asserted' },
  ])) throw new Error('receipt evidence grounding is not exact')
  exact(redemption.authzen_request, ['subject', 'action', 'resource', 'context'], 'AuthZEN request')
  exact(redemption.authzen_request.subject, ['id'], 'AuthZEN request subject')
  exact(redemption.authzen_request.action, ['name'], 'AuthZEN request action')
  exact(redemption.authzen_request.resource, ['id', 'type'], 'AuthZEN request resource')
  exact(redemption.authzen_request.context, ['arguments_hash', 'receiver_nonce', 'run_id'], 'AuthZEN request context')
  exact(redemption.authzen_response, ['decision', 'context'], 'AuthZEN response')
  exact(redemption.authzen_response.context, ['authority_epoch', 'policy_hash', 'request_hash'], 'AuthZEN response context')
  exact(redemption.effect_arguments, ['value'], 'effect arguments')
  if (redemption.effect_arguments.value !== 'alpha-mediated') throw new Error('effect arguments changed')
  const argumentsHash = sha256(Buffer.from(canonical(redemption.effect_arguments)))
  const requestHash = sha256(Buffer.from(canonical(redemption.authzen_request)))
  const responseHash = sha256(Buffer.from(canonical(redemption.authzen_response)))
  const bindings = { run_id: grant.run_id, receiver_id: RECEIVER, counterparty_id: COUNTERPARTY, target: TARGET, effect_class: EFFECT, arguments_hash: argumentsHash }
  for (const [key, expected] of Object.entries(bindings)) {
    if (grant[key] !== expected || mandate[key] !== expected || decision[key] !== expected) throw new Error(`cross-record ${key} binding failed`)
  }
  if (grant.evidence_policy_hash !== policyHash || grant.verifier_hash !== verifierHash || grant.runtime_graph_root !== graph.graph_root || grant.role_set_hash !== roleSetHash || grant.authority_epoch !== authorityEpoch || grant.semantic_epoch !== accepted.semantic_epoch || grant.use_limit !== 1 || grant.issuer_role !== 'target') throw new Error('grant context binding failed')
  if (mandate.issuer_role !== 'authorization' || decision.issuer_role !== 'boundary' || decision.decision !== 'PERMIT' || decision.receiver_nonce !== redemption.receiver_nonce) throw new Error('mandate or boundary role binding failed')
  if (!TIME.test(grant.valid_from) || !TIME.test(grant.valid_until) || mandate.valid_from !== grant.valid_from || mandate.valid_until !== grant.valid_until) throw new Error('validity interval binding failed')
  if (decision.request_hash !== requestHash || decision.response_hash !== responseHash || decision.evidence_policy_hash !== policyHash || decision.authority_epoch !== authorityEpoch || decision.semantic_epoch !== accepted.semantic_epoch) throw new Error('boundary decision binding failed')
  if (redemption.authzen_request.subject.id !== COUNTERPARTY || redemption.authzen_request.action.name !== EFFECT || redemption.authzen_request.resource.id !== TARGET || redemption.authzen_request.resource.type !== 'receiver-state' || redemption.authzen_request.context.arguments_hash !== argumentsHash || redemption.authzen_request.context.receiver_nonce !== redemption.receiver_nonce || redemption.authzen_request.context.run_id !== grant.run_id) throw new Error('AuthZEN request binding failed')
  if (redemption.authzen_response.decision !== true || redemption.authzen_response.context.authority_epoch !== authorityEpoch || redemption.authzen_response.context.policy_hash !== policyHash || redemption.authzen_response.context.request_hash !== requestHash) throw new Error('AuthZEN response binding failed')
  const receiptDigest = (value) => sha256(Buffer.from(`${canonical(value)}\n`))
  const bundleRoot = sha256(Buffer.from(canonical({
    profile: 'bulla.effect-evidence-bundle/0.1-experimental',
    grant_receipt_sha256: receiptDigest(redemption.grant),
    mandate_receipt_sha256: receiptDigest(redemption.mandate),
    boundary_decision_receipt_sha256: receiptDigest(redemption.boundary_decision),
    authzen_request_sha256: requestHash,
    authzen_response_sha256: responseHash,
    effect_arguments_hash: argumentsHash,
    receiver_nonce: redemption.receiver_nonce,
  })))
  if (bundleRoot !== redemption.evidence_bundle_root) throw new Error('evidence bundle root does not recompute')

  const before = json(root, 'protected-state-before.json')
  const after = json(root, 'protected-state-after.json')
  const beforeRoot = sha256(Buffer.from(canonical(before)))
  const afterRoot = sha256(Buffer.from(canonical(after)))
  exact(before, ['profile', 'receiver_id', 'entries'], 'state before')
  exact(after, ['profile', 'receiver_id', 'entries'], 'state after')
  if (before.profile !== 'bulla.effect-lock-protected-state/0.1-experimental' || after.profile !== before.profile || before.receiver_id !== RECEIVER || after.receiver_id !== RECEIVER || before.entries.length !== 0 || !Array.isArray(after.entries) || after.entries.length > 1) throw new Error('protected state transition is not exact')
  if (after.entries.length === 1) {
    exact(after.entries[0], ['arguments_hash', 'effect_class', 'observation_id', 'run_id'], 'protected state entry')
    if (after.entries[0].arguments_hash !== argumentsHash || after.entries[0].effect_class !== EFFECT || after.entries[0].run_id !== grant.run_id || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(after.entries[0].observation_id)) throw new Error('protected state entry binding failed')
  }
  const response = json(root, 'transcripts/valid-redemption.json')
  const replay = json(root, 'transcripts/exact-replay.json')
  exact(response, ['status', 'body'], 'valid redemption transcript')
  exact(replay, ['status', 'body'], 'replay transcript')
  const redemptionDigest = sha256(Buffer.from(canonical(redemption)))
  if (response.status !== replay.status || canonical(response.body) !== canonical(replay.body)) throw new Error('exact replay does not preserve response bytes')
  let validRedemptionEffectCount
  let grantStatus
  let effectAttestation = null
  let observationId = null
  if (response.status === 200) {
    const responseFields = ['effect_record', 'grant_status', 'new_state_root', 'observation_id', 'prior_state_root', 'profile', 'redemption_digest', 'replay', 'status']
    exact(response.body, responseFields, 'valid redemption response')
    exact(replay.body, responseFields, 'replay response')
    if (after.entries.length !== 1) throw new Error('successful redemption did not commit exactly one effect')
    const effectSubjectFields = ['profile', 'grant_attestation', 'redemption_digest', 'effect_class', 'arguments_hash', 'run_id', 'receiver_id', 'target', 'evidence_policy_hash', 'verifier_hash', 'runtime_graph_root', 'role_set_hash', 'semantic_epoch', 'authority_epoch', 'previous_state_root', 'new_state_root', 'observation_id', 'issuer_role']
    const effectSubject = verifyReceipt(response.body.effect_record, accepted.receiver_issuer, 'effect.execute', effectSubjectFields, 'effect record')
    if (canonical(response.body.effect_record.evidence_refs) !== canonical([{ name: 'redemption', hash: redemptionDigest, grounding: 'self_asserted' }])) throw new Error('effect record grounding is not exact')
    if (response.body.profile !== 'bulla.effect-redemption/0.1-experimental' || response.body.status !== 'COMMITTED' || response.body.grant_status !== 'CONSUMED' || response.body.replay !== false || response.body.observation_id !== after.entries[0].observation_id || response.body.redemption_digest !== redemptionDigest || response.body.prior_state_root !== beforeRoot || response.body.new_state_root !== afterRoot || effectSubject.grant_attestation !== redemption.grant.hashes.attestation || effectSubject.redemption_digest !== redemptionDigest || effectSubject.effect_class !== EFFECT || effectSubject.arguments_hash !== argumentsHash || effectSubject.run_id !== grant.run_id || effectSubject.receiver_id !== RECEIVER || effectSubject.target !== TARGET || effectSubject.evidence_policy_hash !== policyHash || effectSubject.verifier_hash !== verifierHash || effectSubject.runtime_graph_root !== graph.graph_root || effectSubject.role_set_hash !== roleSetHash || effectSubject.semantic_epoch !== accepted.semantic_epoch || effectSubject.authority_epoch !== authorityEpoch || effectSubject.previous_state_root !== beforeRoot || effectSubject.new_state_root !== afterRoot || effectSubject.observation_id !== response.body.observation_id || effectSubject.issuer_role !== 'target') throw new Error('effect record or response binding failed')
    validRedemptionEffectCount = 1
    grantStatus = 'CONSUMED'
    effectAttestation = response.body.effect_record.hashes.attestation
    observationId = response.body.observation_id
  } else if (response.status === 403) {
    exact(response.body, ['error'], 'failed legitimate redemption response')
    exact(replay.body, ['error'], 'failed legitimate replay response')
    exact(response.body.error, ['code', 'message'], 'failed legitimate redemption error')
    exact(replay.body.error, ['code', 'message'], 'failed legitimate replay error')
    if (response.body.error.code !== 'LEGITIMATE_PATH_UNAVAILABLE' || response.body.error.message !== 'complete redemption did not produce the protected effect' || after.entries.length !== 0 || afterRoot !== beforeRoot) throw new Error('failed legitimate redemption trace is not coherent')
    validRedemptionEffectCount = 0
    grantStatus = 'UNSPENT'
  } else {
    throw new Error('redemption execution is incomplete or verifier-defective')
  }

  const baseline = json(root, 'transcripts/baseline-direct.json')
  const candidate = json(root, 'transcripts/candidate-direct.json')
  exact(baseline, ['request', 'status', 'body', 'state_changed'], 'baseline transcript')
  exact(candidate, ['request', 'status', 'body', 'state_changed'], 'candidate direct transcript')
  exact(baseline.request, ['effect_key', 'mediated', 'request_id', 'run_id', 'value'], 'baseline direct request')
  exact(baseline.body, ['anchor_id', 'evidence_hash', 'mediated', 'observation_id', 'operation_ref', 'phase', 'protocol', 'request_id', 'run_id'], 'baseline direct response')
  exact(candidate.request, ['effect_key', 'mediated', 'request_id', 'run_id', 'value'], 'candidate direct request')
  const baselineOperationRef = sha256(Buffer.from(canonical({ tool_name: EFFECT, value: baseline.request.value })))
  const baselineEvidenceHash = sha256(Buffer.from(canonical({ anchor_id: 'synthetic-receiver-effect', observation_id: baseline.body.observation_id, operation_ref: baselineOperationRef, transport_status: 'MCP_IS_ERROR_FALSE' })))
  if (baseline.status !== 200 || baseline.state_changed !== true || baseline.request.effect_key !== 'permit:baseline-direct-mediated:request-1' || baseline.request.run_id !== 'baseline-direct-mediated' || baseline.request.request_id !== 'request-1' || baseline.request.mediated !== true || baseline.request.value !== 'alpha-mediated' || baseline.body.anchor_id !== 'synthetic-receiver-effect' || baseline.body.mediated !== true || baseline.body.phase !== 'effect' || baseline.body.protocol !== 'mcp' || baseline.body.request_id !== baseline.request.request_id || baseline.body.run_id !== baseline.request.run_id || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(baseline.body.observation_id) || baseline.body.operation_ref !== baselineOperationRef || baseline.body.evidence_hash !== baselineEvidenceHash) throw new Error('frozen baseline bypass did not commit')
  if (candidate.request.effect_key !== 'permit:direct' || candidate.request.run_id !== grant.run_id || candidate.request.request_id !== 'request-direct' || candidate.request.mediated !== true || candidate.request.value !== 'alpha-mediated') throw new Error('candidate direct request is not the frozen bypass probe')
  let candidateUnmediatedEffectCommitted
  if (candidate.status === 403) {
    exact(candidate.body, ['error'], 'candidate direct response')
    exact(candidate.body.error, ['code', 'message'], 'candidate direct error')
    if (candidate.state_changed !== false || candidate.body.error.code !== 'REDEMPTION_REQUIRED' || candidate.body.error.message !== 'protected effect requires complete redemption') throw new Error('candidate direct rejection is not coherent')
    candidateUnmediatedEffectCommitted = false
  } else if (candidate.status === 200) {
    exact(candidate.body, ['arguments_hash', 'effect_class', 'observation_id', 'profile', 'run_id', 'status'], 'candidate bypass response')
    if (candidate.state_changed !== true || candidate.body.profile !== 'bulla.complete-effect-mediation-candidate-bypass/0.1-experimental' || candidate.body.status !== 'COMMITTED' || candidate.body.effect_class !== EFFECT || candidate.body.arguments_hash !== argumentsHash || candidate.body.run_id !== grant.run_id || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u.test(candidate.body.observation_id)) throw new Error('candidate bypass trace is not coherent')
    candidateUnmediatedEffectCommitted = true
  } else {
    throw new Error('candidate direct execution is incomplete or verifier-defective')
  }

  const closure = exact(json(root, 'source-closure.json'), ['profile', 'baseline', 'candidate'], 'source closure')
  if (closure.profile !== 'bulla.complete-effect-mediation-source-closure/0.1-experimental') throw new Error('source closure profile is not accepted')
  const baselineSourceRoot = sourceRoot(root, closure, 'baseline')
  const candidateSourceRoot = sourceRoot(root, closure, 'candidate')
  const disposition = deriveDisposition({
    baseline_effect_committed: baseline.state_changed,
    candidate_unmediated_effect_committed: candidateUnmediatedEffectCommitted,
    valid_redemption_effect_count: validRedemptionEffectCount,
    grant_consumed: grantStatus === 'CONSUMED',
    exact_replay: canonical(response.body) === canonical(replay.body),
    every_declared_path_mediated: graph.result === 'ESTABLISHED_IN_DECLARED_GRAPH',
  })
  const dispositionBasis = {
    EFFECT_LOCK_SEPARATES: ['BASELINE_DIRECT_EFFECT_COMMITTED', 'CANDIDATE_DIRECT_EFFECT_REJECTED', 'VALID_REDEMPTION_COMMITTED_ONCE', 'DECLARED_PATHS_MEDIATED'],
    WRAPPER_ONLY: ['CANDIDATE_DIRECT_EFFECT_COMMITTED'],
    NO_SEPARATION: ['VALID_REDEMPTION_DID_NOT_COMMIT_EFFECT'],
  }[disposition]
  return {
    profile: REPORT_PROFILE,
    maturity: { distribution: 'SOURCE_ONLY', operation: 'PROJECT_OPERATED', boundary: 'DECLARED' },
    protected_effect: { effect_class: EFFECT, target: TARGET, arguments_hash: argumentsHash, receiver_id: RECEIVER },
    source_roots: { baseline: baselineSourceRoot, candidate: candidateSourceRoot },
    state_roots: { before: beforeRoot, after: afterRoot },
    records: {
      grant_attestation: redemption.grant.hashes.attestation,
      redemption_digest: redemptionDigest,
      effect_attestation: effectAttestation,
      observation_id: observationId,
    },
    traces: {
      baseline_direct: { http_status: baseline.status, effect_committed: baseline.state_changed, response_sha256: sha256(Buffer.from(`${canonical(baseline.body)}\n`)) },
      candidate_direct: { http_status: candidate.status, effect_committed: candidate.state_changed, response_sha256: sha256(Buffer.from(`${canonical(candidate.body)}\n`)) },
      valid_redemption: { http_status: response.status, effect_count: validRedemptionEffectCount, grant_status: grantStatus, response_sha256: sha256(Buffer.from(`${canonical(response.body)}\n`)) },
      exact_replay: { http_status: replay.status, effect_count: validRedemptionEffectCount, response_bytes_equal: canonical(response.body) === canonical(replay.body), response_sha256: sha256(Buffer.from(`${canonical(replay.body)}\n`)) },
    },
    declared_graph_mediation: graph,
    runtime_evidence: {
      workers_harness: 'PROJECT_OPERATED',
      packet_reproduction: 'TRANSCRIPT_AND_DERIVATION_ONLY',
      packet_reexecutes_durable_object: false,
    },
    residual_boundary: RESIDUAL_BOUNDARY,
    disposition_basis: dispositionBasis,
    disposition,
  }
}

export function deriveDisposition(input) {
  exact(input, ['baseline_effect_committed', 'candidate_unmediated_effect_committed', 'valid_redemption_effect_count', 'grant_consumed', 'exact_replay', 'every_declared_path_mediated'], 'disposition input')
  if (input.baseline_effect_committed !== true || input.valid_redemption_effect_count !== 1 || input.grant_consumed !== true || input.exact_replay !== true) return 'NO_SEPARATION'
  if (input.candidate_unmediated_effect_committed === true || input.every_declared_path_mediated !== true) return 'WRAPPER_ONLY'
  return 'EFFECT_LOCK_SEPARATES'
}

export async function main(argv = process.argv.slice(2)) {
  if (argv.length !== 1) throw new Error('usage: node run.mjs PACKET_ROOT')
  const report = computeReport(argv[0])
  const expected = json(resolve(argv[0]), 'expected-report.json')
  if (canonical(report) !== canonical(expected)) throw new Error('recomputed report differs from expected report')
  process.stdout.write(`${JSON.stringify(report, null, 2)}\n`)
}

if (process.argv[1] && realpathSync(fileURLToPath(import.meta.url)) === realpathSync(resolve(process.argv[1]))) {
  main().catch((error) => { process.stderr.write(`${error.message}\n`); process.exitCode = 1 })
}
