${e(clip(storedText(data.operationId,'Operation not recorded')))}
${e(clip(storedText(offer.statement,''),240))}
// @requirements REQ-PRODUCT-MOBILE // @requirements REQ-PRODUCT-A11Y // @requirements REQ-PRODUCT-CONTRACT-ACTIONS // @requirements REQ-EU-CONSENT REQ-CA-MEANINGFUL REQ-EU-MARKETING REQ-CA-CASL-OPTIN // @requirements REQ-PRODUCT-SCOPE-GUARDS import {adminCss} from './admin-style.js'; // @requirements REQ-EU-ORDER-ACTION REQ-PRODUCT-CF-ADMIN import {paidOrderCard,paidOrderDetail} from './order-render.js'; import {orderAdminCss} from './order-admin-style.js'; import {normalizeAdminPresentation} from './presentation.js'; import type {AdminPresentation} from './types.js'; import {scopeGuardFields} from './scope-guard-policy.js'; // @requirements REQ-EU-RETENTION-ERASURE // @requirements REQ-PRODUCT-EVIDENCE-LIFECYCLE import {recordQueryParams} from './export.js'; import type {EvidenceExportSegment} from './export.js'; import { boundedText, recordFacts } from './records.js'; import { documentSections,canonicalJson } from './history.js'; import { sourceDiff } from './source-diff.js'; import type { EvidenceRecord, JsonValue, RecordPage, RecordQuery } from './types.js'; export const escapeHtml = (value: string): string => value.replace(/[&<>"']/gu, char => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[char]!); const clip = (value: string, length = 180) => value.length > length ? `${value.slice(0, length)}…` : value; const display = (value: JsonValue) => typeof value === 'string' ? value : JSON.stringify(value, null, 2); const storedText = (value: JsonValue | undefined, fallback = 'Not recorded') => value === undefined ? fallback : display(value); export function readableTime(value:JsonValue|undefined):string { if(typeof value!=='string'||!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/u.test(value)||!Number.isFinite(Date.parse(value))) return escapeHtml(storedText(value)); const label=new Intl.DateTimeFormat('en-GB',{day:'numeric',month:'short',year:'numeric',hour:'2-digit',minute:'2-digit',second:'2-digit',hour12:false,timeZone:'UTC'}).format(new Date(value)); return ``; } export interface RenderOptions extends AdminPresentation { basePath: string; title: string; scopeLabel: string; nonce: string; exportEnabled?:boolean; sourceEnabled?:boolean; catalogReviewEnabled?:boolean; orderArchiveEnabled?:boolean; orderConfirmationEnabled?:boolean } export function renderWorkspaceShell(body: string, options: RenderOptions, extraHead = '', bodyClass = ''): string { if (!/^\/[a-zA-Z0-9_-]+(?:\/[a-zA-Z0-9_-]+)*$/u.test(options.basePath) || !/^[a-f0-9]{32}$/u.test(options.nonce) || !boundedText(options.title, 120) || !boundedText(options.scopeLabel, 200)) throw new Error('Invalid presentation options.'); const e = escapeHtml, presentation=normalizeAdminPresentation(options); const links=presentation.navigation?.length?presentation.navigation:[{label:'Evidence search',href:options.basePath}]; const navIcon=(label:string)=>{const key=label.toLowerCase();const path=key.includes('setup')?'M4 6h16M4 12h16M4 18h16M8 3v6M16 9v6M10 15v6':key.includes('histor')||key.includes('release')||key.includes('revision')?'M3 11a9 9 0 1 1 2.5 7M3 4v7h7M12 7v5l3 2':key.includes('agreement')||key.includes('terms')?'M7 3h7l4 4v14H6V3h1m7 0v5h4M9 12h6M9 16h4':key.includes('export')?'M12 3v12m-4-4 4 4 4-4M5 15v6h14v-6':key.includes('evidence')||key.includes('search')?'m15 15 6 6M17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0':key.includes('choice')||key.includes('permission')?'M9 12l2 2 4-4M12 3 4 6v6c0 5 8 9 8 9s8-4 8-9V6l-8-3Z':'M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z';return ``;}; const navigation=links.map(link=>`${e(link.label)}`).join(''); return `
${e(action)} · revision ${e(storedText(data.revision))}${notice.mode==='preview'?' · Preview record':''}
Historical browser report. Later choices, expiry or scope changes may supersede it.
${value===true?'Reported allow':value===false?(noticeScopeBlocked(notice,id)?'Kept off by scope guard':'Reported decline'):'Unrecognized value'}
Choice expires: ${readableTime(expiry[id])}
${purposeDisclosure(notice,id)}${data.action==='revoke-all'&&!Object.hasOwn(purposes,id)?'Cleared by revoke-all; this purpose was added after the submitted notice.
':''}${e(storedText(wording.title))}
${e(storedText(wording.summary))}
${e(storedText(wording.preferencesIntro))}
${e(storedText(wording.essentialNote))}
${['rejectLabel','acceptLabel','saveLabel'].map(key=>e(storedText(wording[key]))).join(' · ')}
Choice expiry is distinct from evidence retention. The host configures retention and deletion separately. Delayed first delivery of revoke-all can conservatively revoke a newer grant.
Evidence lifecycle
${retired?'This context rejects new commands and historical retries. Purge removes only its matching ledger payloads.':'This context remains live. A hold protects its payloads from the lifecycle purge.'}
${hold.active===true?'Active — further purge steps blocked':'No active stored hold'}
${hold.active===true?`Review: ${readableTime(hold.reviewAt)}. Reaching this date does not release the hold.`:'The host must reassess eligibility before each purge step.'}
${e(storedText(progress.deleted))}
${e(storedText(progress.scanned))} key${progress.scanned===1?'':'s'} examined across ${e(storedText(progress.batches))} committed batch${progress.batches===1?'':'es'}. These counts describe this scan, not all personal data.
Retired processing contexts remain blocked. They do not become empty live opt-out streams.
':''}Completion applies to the scoped scan. Minimal lifecycle metadata and shared policy archives remain; backups, exports and host copies need separate handling. Reapply the authoritative retirement manifest and restart scanning before reopening restored storage.
${escapeHtml(storedText(data.description))}
${facts([['Context digest',data.contextRef],['Recorded lifecycle state',data.status]])}${typeof data.processing==='string'?`${escapeHtml(data.processing)}
`:''}This is a minimized inspection projection, not the original event or a historical receipt. The lifecycle view records purge progress separately.
Visitor-provided claims, received by the host. Receipt, confirmation delivery and application fulfillment are separate.
${escapeHtml(contractDeliveryStatus(job))}
${escapeHtml(storedText(job.attempts))} attempt${job.attempts===1?'':'s'} · ${readableTime(job.updatedAt)}
${channel==='acknowledgement'?'Must run independently of contract matching. Provider acceptance does not prove recipient delivery.':'No cancellation, refund or effective end date is inferred from this handoff.'}
${escapeHtml(storedText(wording.statement))}
${escapeHtml(storedText(wording.confirmLabel))}
${escapeHtml(storedText(ack.text))}${facts([['Action definition',definition.definitionId],['Form revision',definition.revision],['Profile',definition.profile],['Request ID',request.requestId],['Request SHA-256',receipt.requestSha256],['Acknowledgement SHA-256',ack.sha256],['Application delivery ID',objectData(jobs.application).deliveryId],['Confirmation delivery ID',objectData(jobs.acknowledgement).deliveryId]])}Archived form documents do not establish the terms governing the original contract. The host owns admission, prompt dispatch, contract/identity matching, eligibility, fulfillment, retention and external copies.
${offer.mode==='preview'?'Preview record · ':''}One purpose and channel. The recorded action is shown alongside the permission state evaluated when this page was read.
${d.action==='grant'?'Grant recorded':d.action==='withdraw'?'Withdrawal recorded':'Action not recorded'}
Event revision ${e(storedText(d.revision))}
${state.permitted===true?'Permission currently recorded':state.permitted===false?'No current permission':'Evaluation not available'}
${e(({granted:'The grant matches the current permission offer.',withdrawn:'The current recorded choice is a withdrawal.','offer-changed':'The permission information changed after this grant.',inactive:'No permission offer is currently active.','scope-restricted':'This context needs a separate supported process.','not-granted':'No grant is recorded for this contact generation.'} as Record
${e(storedText(purpose.description))}
${e(storedText(wording.statement))}
${e(storedText(wording.optionality))}
${e(storedText(wording.withdrawalExplanation))}
The host must evaluate the state again at downstream use and apply its reviewed rules. A receipt, page snapshot or asserted grant does not establish identity, address ownership, lawful marketing, message delivery, or fulfillment of withdrawal.
${notice.mode==='preview'?'Preview record · ':''}Separate from cookie permission. These records add restrictions; they never grant processing.
${e(list(data.activities))}
${e(list(data.restrictions))}
Historical revision ${e(storedText(data.revision))}
${e(list(latest.restrictions))}
Revision ${e(storedText(head.revision))}. Later events may change this view.
${e(storedText(wording.title))}
${e(storedText(wording.description))}
${e(storedText(wording.actionLabel))}
The host assigns context and provenance. A stored event does not prove a human click, complete identity matching, or downstream cessation and notifications. The host supplies those operations, retention and erasure.
${escapeHtml(storedText(details.description))}
${services.length?`Services: ${services.map(value=>{const s=objectData(value);return `${escapeHtml(storedText(s.name))} (${escapeHtml(storedText(s.provider))})`;}).join(', ')}
`:''}${e(clip(storedText(data.operationId,'Operation not recorded')))}
${e(clip(storedText(offer.statement,''),240))}
${e(agreement)}
`:''}${factsHtml(record)}${e(summary)}
${permissionHistoryLink(record,options.basePath)}Evidence search
${e(contractView?'Review the exact declaration and its two independent handoffs. A recorded request does not mean a contract has ended.':orderView?'Inspect received requests, their retained prices and the information supplied before the order action.':page.records.length&&page.records.every(record=>agreementSummary(record))?'Inspect the statement and document version attached to each agreement.':'Search recorded choices, agreements and document releases.')}
Authorized scope: ${e(options.scopeLabel)}
${page.nextAfter === undefined ? 'Try another search or clear your filters.' : 'More records remain to examine. Continue this search to inspect the next segment.'}
Results come from the authorized store, ${permissionTimeline?'shown in recorded event order for this contact reference':'ordered by record key'}. Counts describe this page, not the full store.
Agreement record
Authorized scope: ${e(options.scopeLabel)}
${e(storedText(offer.statement))}
${e(storedText(offer.actionLabel))}
This records an assertion received by the host. It does not prove a human click, identity, enforceability, delivery, or completion of the related application operation.
${e(JSON.stringify(record.data,null,2))}Inspect the selected catalog and site-use facts bound to this release.
Inspect catalog review →Inspect the exact Markdown or MDX retained with this release. Source is displayed as text and never evaluated.
${data.sourceKinds.filter(kind => typeof kind === 'string' && ['privacy','cookies','terms'].includes(kind)).map(kind => `${e(String(kind))} source →`).join(' · ')}
${e(releaseSummary(record) ?? '')}
${typeof data.changeNote === 'string' ? `${e(data.changeNote)}
` : ''}${typeof data.actor === 'string' ? `Recorded actor: ${e(data.actor)}
` : ''}An archive records supplied content, not proof of publication, delivery, acceptance, or valid consent. Archived HTML is retained in storage and never executed here.
${isRelease ? 'Immutable release' : 'Record detail'}
Record ${e(record.id)}
` : choice ? `${e(choice.replace('Cookie choices · ',''))}
` : ''}Authorized scope: ${e(options.scopeLabel)}
${choice||lifecycle||retired ? '' : 'The fields below reflect stored values. Absent fields are omitted; identity, consent, and legal validity are not inferred.
'}${lifecyclePanel(record)}${retiredPanel(record)}${release}${catalogReview}${sources}${consentPanel(record)}${processingPanel(record)}${permissionPanel(record,options.basePath)}${contractPanel(record)}${e(value)}
` : `${e(display(value!))}`}${e(JSON.stringify(record.data, null, 2))}${canonicalJson(oldManifest.catalogReview)===canonicalJson(newManifest.catalogReview)?'Selected catalog review unchanged.':'Selected catalog review changed; document text and rendering are compared separately.'}
Compare selected service references →${oldAuthoring.sourceSha256 === newAuthoring.sourceSha256 ? 'Authored source unchanged.' : 'Authored source changed.'} ${oldAuthoring.bodySha256 === newAuthoring.bodySha256 ? 'Rendered document body unchanged.' : 'Rendered document body changed.'}
Compare retained source →${e(old?.text ?? '—')}${e(current?.text ?? '—')}Document comparison
Authorized scope: ${e(options.scopeLabel)}
Text comparison supports human review. It does not decide legal materiality, whether new acceptance is needed, or whether consent remains valid.
${oldHash.contentSha256 === newHash.contentSha256 ? 'Structured content hash unchanged.' : 'Structured content hash changed.'} ${oldHash.sha256 === newHash.sha256 ? 'Rendered HTML hash unchanged.' : 'Rendered HTML hash changed (includes presentation and document metadata).'}
${catalogComparison}${sourceComparison}${titleChanged ? `Before: ${e(String(beforeDoc.title))}
After: ${e(String(afterDoc.title))}
Section order or membership changed. Review the complete structured documents for their full order.
' : ''}No section text changes.
'}${e(JSON.stringify(beforeDoc,null,2))}${e(JSON.stringify(afterDoc,null,2))}${e(String(entry.data.format).toUpperCase())} · ${e(storedText(entry.authoring.sourceBytes))} UTF-8 bytes
${e(storedText(entry.data.title))} →${changed ? 'Authored source changed.' : 'Authored source unchanged.'} ${first.authoring.bodySha256===next.authoring.bodySha256 ? 'Rendered document body unchanged.' : 'Rendered document body changed.'}
${diff.precise ? 'Changed ranges include two surrounding lines for context.' : 'This large comparison uses one bounded range, with surrounding context.'} Newline encoding and byte-only differences remain visible through the source hashes; complete source is retained below.
${diff.ranges.map(range=>`${e(range.before.join('\n') || 'No lines in this range.')}${e(range.after.join('\n') || 'No lines in this range.')}${e(entry.source)}Private authoring archive
Authorized scope: ${e(options.scopeLabel)}
Exact build input, displayed as text. MDX expressions, imports and components are never executed in this workspace.
Evidence export
Download one JSON segment using the current search filters. The file includes those filters and any continuation cursor.
Authorized scope: ${e(segment.scopeLabel)}
Selection preview
Preview read completed: ${readableTime(segment.read.completedAt)}
Downloads a fresh read of this segment. Records may differ from this preview. Every download is authorized again by your host.
${next===undefined?'This is the end reported for the current filtered read. Records can change between reads; it is not proof that all evidence or application data has been exported.':'More keys may remain to examine, even when this segment has no matches. Follow the download’s nextReview or nextDownload link to continue from its actual cursor. Save each segment separately.'}
${nextReview?'The next preview link uses this preview’s cursor. Use the JSON file’s continuation links when assembling a download sequence.
':''}