Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
<script lang="ts">
|
Phase 2, step 8: the open action of /inspect
After steps 1 to 8, a valid capsule whose date has passed on the device
clock can be opened in the page: steps 9 to 18 of spec section 63 with
open, loaded on demand with a dynamic import (opener.ts), so noble and
age-encryption stay out of the first load of every page.
- The release is supplied directly by the person (spec 63, step 10):
drand's JSON answer or the bare signature, pasted after opening the
drand URL the page links to, or the release in the record of an
official fixture. The page never fetches it and reads only its round
and signature (spec 11, 13). The CSP is unchanged.
- time_and_key credentials: a .dkk (readAccessKey reads at most
12 bytes + 16 MiB + 1) or age identities, one per line.
- The plaintext of the person's own file goes to a temporary OPFS file
(tempfile.ts), committed only after step 18 (spec 56), offered for
download and deleted on request, with another capsule, on pagehide
and, if left over, on the next visit. One directory and one Web Lock
per tab keep other tabs' clean-up away from files in use. Without
OPFS, or when the browser refuses it, capsules up to 64 MiB open in
memory. An opening in progress stops when another capsule is loaded.
- opening.ts builds the page model of steps 9 to 18 as the reference
records them; fixtures show their plaintext and compare its SHA-256
with their record.
- licenses.txt: the notices of tlock-js (ibe.ts) and age (bech32.ts),
the license of every package in the client bundle, Vite's and
rolldown's runtime code, and the site's own license. check-build now
fails if a notice is missing, or if a page loads noble, @scure/base
or age-encryption with its first load.
- The home page no longer says that the page never asks for keys.
Checked in the browser on the production build: the time_only,
time_and_key_portable (with its .dkk) and time_and_key_recipients (with
a pasted identity) fixtures open with the SHA-256 of their records; a
tampered signature fails at step 10 and a tampered STREAM chunk at step
17, with no download and no file left; an own file opens to OPFS,
downloads without a CSP violation and is deleted with its lock; a left
over directory goes on the next visit; no request leaves the origin.
An adversarial review (four dimensions, each finding checked by a
refuter) confirmed 15 findings, all fixed here.
2611 tests; coverage 100 % of the new modules, now a threshold.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
import type { Snippet } from 'svelte';
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
import type { Report, Comparison } from '$lib/inspector/report.ts';
|
|
|
|
|
import {
|
|
|
|
|
displayText,
|
|
|
|
|
errorGloss,
|
|
|
|
|
escapeInvisible,
|
|
|
|
|
formatByteCount,
|
|
|
|
|
formatDateTime,
|
|
|
|
|
formatInteger,
|
|
|
|
|
formatRelative,
|
|
|
|
|
policyGloss,
|
|
|
|
|
} from '$lib/inspector/format.ts';
|
|
|
|
|
import StepList from './StepList.svelte';
|
|
|
|
|
import ExtensionList from './ExtensionList.svelte';
|
|
|
|
|
|
|
|
|
|
let {
|
|
|
|
|
report,
|
|
|
|
|
nowMs,
|
|
|
|
|
timeZone,
|
Phase 2, step 8: the open action of /inspect
After steps 1 to 8, a valid capsule whose date has passed on the device
clock can be opened in the page: steps 9 to 18 of spec section 63 with
open, loaded on demand with a dynamic import (opener.ts), so noble and
age-encryption stay out of the first load of every page.
- The release is supplied directly by the person (spec 63, step 10):
drand's JSON answer or the bare signature, pasted after opening the
drand URL the page links to, or the release in the record of an
official fixture. The page never fetches it and reads only its round
and signature (spec 11, 13). The CSP is unchanged.
- time_and_key credentials: a .dkk (readAccessKey reads at most
12 bytes + 16 MiB + 1) or age identities, one per line.
- The plaintext of the person's own file goes to a temporary OPFS file
(tempfile.ts), committed only after step 18 (spec 56), offered for
download and deleted on request, with another capsule, on pagehide
and, if left over, on the next visit. One directory and one Web Lock
per tab keep other tabs' clean-up away from files in use. Without
OPFS, or when the browser refuses it, capsules up to 64 MiB open in
memory. An opening in progress stops when another capsule is loaded.
- opening.ts builds the page model of steps 9 to 18 as the reference
records them; fixtures show their plaintext and compare its SHA-256
with their record.
- licenses.txt: the notices of tlock-js (ibe.ts) and age (bech32.ts),
the license of every package in the client bundle, Vite's and
rolldown's runtime code, and the site's own license. check-build now
fails if a notice is missing, or if a page loads noble, @scure/base
or age-encryption with its first load.
- The home page no longer says that the page never asks for keys.
Checked in the browser on the production build: the time_only,
time_and_key_portable (with its .dkk) and time_and_key_recipients (with
a pasted identity) fixtures open with the SHA-256 of their records; a
tampered signature fails at step 10 and a tampered STREAM chunk at step
17, with no download and no file left; an own file opens to OPFS,
downloads without a CSP violation and is deleted with its lock; a left
over directory goes on the next visit; no request leaves the origin.
An adversarial review (four dimensions, each finding checked by a
refuter) confirmed 15 findings, all fixed here.
2611 tests; coverage 100 % of the new modules, now a threshold.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
opening,
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
}: {
|
|
|
|
|
report: Report;
|
|
|
|
|
/** When the report was made, for the distance to the unlock date. */
|
|
|
|
|
nowMs: number;
|
|
|
|
|
/** The viewer's time zone, for example "Europe/Madrid". */
|
|
|
|
|
timeZone: string | undefined;
|
Phase 2, step 8: the open action of /inspect
After steps 1 to 8, a valid capsule whose date has passed on the device
clock can be opened in the page: steps 9 to 18 of spec section 63 with
open, loaded on demand with a dynamic import (opener.ts), so noble and
age-encryption stay out of the first load of every page.
- The release is supplied directly by the person (spec 63, step 10):
drand's JSON answer or the bare signature, pasted after opening the
drand URL the page links to, or the release in the record of an
official fixture. The page never fetches it and reads only its round
and signature (spec 11, 13). The CSP is unchanged.
- time_and_key credentials: a .dkk (readAccessKey reads at most
12 bytes + 16 MiB + 1) or age identities, one per line.
- The plaintext of the person's own file goes to a temporary OPFS file
(tempfile.ts), committed only after step 18 (spec 56), offered for
download and deleted on request, with another capsule, on pagehide
and, if left over, on the next visit. One directory and one Web Lock
per tab keep other tabs' clean-up away from files in use. Without
OPFS, or when the browser refuses it, capsules up to 64 MiB open in
memory. An opening in progress stops when another capsule is loaded.
- opening.ts builds the page model of steps 9 to 18 as the reference
records them; fixtures show their plaintext and compare its SHA-256
with their record.
- licenses.txt: the notices of tlock-js (ibe.ts) and age (bech32.ts),
the license of every package in the client bundle, Vite's and
rolldown's runtime code, and the site's own license. check-build now
fails if a notice is missing, or if a page loads noble, @scure/base
or age-encryption with its first load.
- The home page no longer says that the page never asks for keys.
Checked in the browser on the production build: the time_only,
time_and_key_portable (with its .dkk) and time_and_key_recipients (with
a pasted identity) fixtures open with the SHA-256 of their records; a
tampered signature fails at step 10 and a tampered STREAM chunk at step
17, with no download and no file left; an own file opens to OPFS,
downloads without a CSP violation and is deleted with its lock; a left
over directory goes on the next visit; no request leaves the origin.
An adversarial review (four dimensions, each finding checked by a
refuter) confirmed 15 findings, all fixed here.
2611 tests; coverage 100 % of the new modules, now a threshold.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
/** The opening of the capsule, after steps 1 to 8. */
|
|
|
|
|
opening?: Snippet;
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
} = $props();
|
|
|
|
|
|
|
|
|
|
let copyStatus = $state('');
|
|
|
|
|
let jsonOpen = $state(false);
|
|
|
|
|
let copyButton: HTMLButtonElement | undefined = $state();
|
|
|
|
|
|
|
|
|
|
const unlockMs = $derived(report.unlock?.epochMs);
|
|
|
|
|
const fileName = $derived(displayText(report.fileName));
|
|
|
|
|
const shownJSON = $derived(escapeInvisible(report.json));
|
|
|
|
|
|
|
|
|
|
async function copyJSON(): Promise<void> {
|
|
|
|
|
copyStatus = '';
|
|
|
|
|
try {
|
|
|
|
|
await navigator.clipboard.writeText(report.json);
|
|
|
|
|
copyStatus = 'JSON copiado.';
|
|
|
|
|
return;
|
|
|
|
|
} catch {
|
|
|
|
|
// No Clipboard API (an insecure context, a denied permission): fall
|
|
|
|
|
// back to a selected textarea and the legacy copy command.
|
|
|
|
|
}
|
|
|
|
|
if (legacyCopy(report.json)) {
|
|
|
|
|
copyStatus = 'JSON copiado.';
|
|
|
|
|
} else {
|
|
|
|
|
jsonOpen = true;
|
|
|
|
|
copyStatus = 'El navegador no deja copiar desde la página: selecciona el JSON de abajo y cópialo.';
|
|
|
|
|
}
|
|
|
|
|
copyButton?.focus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function legacyCopy(text: string): boolean {
|
|
|
|
|
const area = document.createElement('textarea');
|
|
|
|
|
area.value = text;
|
|
|
|
|
area.readOnly = true;
|
|
|
|
|
area.className = 'visually-hidden';
|
|
|
|
|
document.body.append(area);
|
|
|
|
|
area.select();
|
|
|
|
|
let ok = false;
|
|
|
|
|
try {
|
|
|
|
|
ok = document.execCommand('copy');
|
|
|
|
|
} catch {
|
|
|
|
|
ok = false;
|
|
|
|
|
}
|
|
|
|
|
area.remove();
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function stanzaTypes(list: readonly { type: string }[]): string {
|
|
|
|
|
return list.length === 0 ? 'ninguno' : list.map((s) => s.type).join(', ');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function comparisonState(c: Comparison): string {
|
|
|
|
|
return c.match ? 'coincide' : 'no coincide';
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<section class="report" aria-labelledby="report-title">
|
|
|
|
|
<header class="report-head">
|
|
|
|
|
<div class="file">
|
|
|
|
|
<h2 id="report-title" tabindex="-1">{fileName.text}</h2>
|
|
|
|
|
<p class="muted">
|
|
|
|
|
{formatByteCount(report.size)}{#if report.readLength < report.size}. Se leyeron los primeros {formatByteCount(
|
|
|
|
|
report.readLength,
|
|
|
|
|
)}: el resto {report.prelude ? 'de PAYLOAD_AGE' : 'del fichero'} no interviene en los pasos 1 a 8{/if}.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="copy">
|
|
|
|
|
<button class="button quiet" type="button" onclick={copyJSON} bind:this={copyButton}>Copiar JSON</button>
|
|
|
|
|
<p class="copy-status" role="status">{copyStatus}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<div class={['verdict', report.valid ? 'valid' : 'invalid']}>
|
|
|
|
|
<div class="state">
|
|
|
|
|
{#if report.valid}
|
|
|
|
|
<p class="state-word">Estructura válida</p>
|
|
|
|
|
<p>
|
Align with DateKeys v0.8.2 at 3820066
Finishes the interrupted alignment of 3305bbb. The TypeScript now
follows the reference at 3820066 on steps 1 to 8, decoding and profile
validation:
- §69.1 precedence: the schema head is read strictly (a null or simple
version is ERR_NON_CANONICAL_CBOR, version 2 is ERR_UNSUPPORTED_VERSION
whatever follows) and every CDDL rule, including access_policy,
extension_version and the 64-extension cap read from the array head,
is checked before the DateKey; the wideUint path that imitated the
old Go order is gone.
- §19: CR or LF in dk1_ is ERR_DATEKEY_INVALID; §15: a round at exactly
9999-12-31T23:59:59Z is valid; §12.1: period above one day is
rejected on decode and pin; BODY_LEN 0 is ERR_INTEGRITY.
- Inspector texts no longer call header data authenticated at step 15
(§55.1: binding, never authorship or date); the fixture list ignores
the new *.inspect.json goldens.
The harness runs every shared Go vector: dk1.json 30, quicknet_rounds
17, profile 1, cbor.json 103 generic and 135 schema vectors,
mutations.json 31 through inspect with 24 phase-2 cases skipped and
counted, inspect_differential.json 1,825, and the five inspect goldens
byte-identical. A differential of 483,527 inputs against the Go
reference found no disagreement on verdict, code or step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
Supera los pasos 1 a 8 de §63 sin red y sin secretos. Es una comprobación de estructura: la cabecera pública solo
|
|
|
|
|
queda vinculada al control al abrir la cápsula (paso 15), y ni siquiera entonces prueba quién la escribió ni
|
|
|
|
|
cuándo (§55.1).
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
</p>
|
Read capsule format 2 of spec v0.9
Syncs testdata with datekeys-go at spec-v0.9 (7e2d83c) and moves the
reader to the DateKeys Protocol Specification v0.9. Both capsule formats
are read; a format 1 capsule keeps the verdict v0.8.2 gave it.
- framing: the VERSION of the prelude is the capsule format, 1 or 2
(Prelude.format, FORMAT_1, FORMAT_2, isFormat).
- control: decodeControl and encodeControl take the format; schema
version 2 adds payload_length (8 bytes, at most L_MAX) and padding
(1 or 2).
- padding.ts: the rules bloque256 and reforzado of spec §29.1, exact up
to L_MAX with BigInt bit lengths and ceil roundings, and the length of
PAYLOAD_AGE.
- open: exactly 16 stanzas in INNER_ACCESS_AGE of format 2 (step 12), P
at step 16, and at step 17 a plaintext of exactly P bytes whose
padding is zero; only the first L bytes are delivered, never the
padding. Step 17 is recorded when it passes, and step 18 gives the
bytes of content, as the reference does. Opened reports the format, L
and, in format 2, the rule and P.
- inspect: the JSON view carries format, as datekeys inspect -json.
- The page shows the format, warns about format 1, and gives the
padding rule and P once a format 2 capsule opens.
Tests: the twelve fixtures, the 125 mutation cases through open from
memory and from a Blob, the 4380 differential cases, padding.json, the
format 2 CBOR vectors, and padding.test.ts against a BigInt statement of
§29.1. The error texts of the 125 corpus cases were compared with
capsule.Open at spec-v0.9. ibe-vectors.json gains the seven format 2
fixtures from scripts/ibe-go-vectors.go; its frozen values are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
|
|
|
{#if report.prelude?.format === 1}
|
|
|
|
|
<p class="format-note">
|
|
|
|
|
Formato 1, el de la v0.8.2: hasta la fecha, esta cápsula deja ver cuántas credenciales tiene y la longitud exacta
|
Format 3, step 3: read capsule format 3 of spec v0.10
Syncs testdata with datekeys-go at the tag spec-v0.10 (cc35d2c) and
moves the reader to the DateKeys Protocol Specification v0.10. The
three capsule formats are read.
- framing: FORMAT_3, and isPadded for formats 2 and 3. control: schema
version 3, with the keys 6 and 7 of version 2. SPEC_VERSION is 0.10.
- open: OpenOptions.sink receives the files of a format 3 capsule
(sink.ts: Sink with begin, create, commit and abort, as capsule.Sink,
and MemorySink). Without one, open rejects with a TypeError right
after step 2, before any request, as ErrSinkRequired. Opened gains
head, verdicts, areaLen and unusableHeadExtensions.
- open3.ts: step 17 of format 3 in its substeps 17.2 to 17.8, as
openBody of the reference: a failure of age or a plaintext whose
length is not P prevails, the first failing substep decides, and the
codes other than ERR_INTEGRITY are reported only after reading
PAYLOAD_AGE to its end. Reads grow with the bytes received, never
with the lengths BODY declares. A failure of the sink is ERR_INTEGRITY
with its text, and the sink is aborted once after begin.
- The page: opener.ts opens the fixtures of format 3 into a
MemorySink; the open panel says that it does not deliver their files
yet, and the glosses of the steps name format 3. check-build.mjs
refuses to ship the heads, salts, comments and paths of the format 3
fixtures.
Tests: the 21 fixtures, format 3 laid out byte by byte from its record
and opened into a sink with its files and verdicts; the 209 cases of
the corpus from memory and from a Blob, with the code, the step and,
new, the exact text of capsule.Open, frozen by
scripts/mutation-go-texts.go in testing/mutation-texts.json, which
replays the corpus as internal/testkit does (its extension validator
texts included); the 5110 differential cases over 14 bases; paths,
path_fold, head_schema and security vectors; the control of schema
version 3 in cbor.json; and step 17 on crafted plaintexts sealed again
to I_PAYLOAD, whose texts capsule.Open gives on the same plaintexts.
ibe-vectors.json gains the nine format 3 fixtures from
scripts/ibe-go-vectors.go; the twelve before are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
|
|
|
de su contenido. Los formatos 2 y 3 ocultan las dos cosas (§55.2).
|
Read capsule format 2 of spec v0.9
Syncs testdata with datekeys-go at spec-v0.9 (7e2d83c) and moves the
reader to the DateKeys Protocol Specification v0.9. Both capsule formats
are read; a format 1 capsule keeps the verdict v0.8.2 gave it.
- framing: the VERSION of the prelude is the capsule format, 1 or 2
(Prelude.format, FORMAT_1, FORMAT_2, isFormat).
- control: decodeControl and encodeControl take the format; schema
version 2 adds payload_length (8 bytes, at most L_MAX) and padding
(1 or 2).
- padding.ts: the rules bloque256 and reforzado of spec §29.1, exact up
to L_MAX with BigInt bit lengths and ceil roundings, and the length of
PAYLOAD_AGE.
- open: exactly 16 stanzas in INNER_ACCESS_AGE of format 2 (step 12), P
at step 16, and at step 17 a plaintext of exactly P bytes whose
padding is zero; only the first L bytes are delivered, never the
padding. Step 17 is recorded when it passes, and step 18 gives the
bytes of content, as the reference does. Opened reports the format, L
and, in format 2, the rule and P.
- inspect: the JSON view carries format, as datekeys inspect -json.
- The page shows the format, warns about format 1, and gives the
padding rule and P once a format 2 capsule opens.
Tests: the twelve fixtures, the 125 mutation cases through open from
memory and from a Blob, the 4380 differential cases, padding.json, the
format 2 CBOR vectors, and padding.test.ts against a BigInt statement of
§29.1. The error texts of the 125 corpus cases were compared with
capsule.Open at spec-v0.9. ibe-vectors.json gains the seven format 2
fixtures from scripts/ibe-go-vectors.go; its frozen values are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
|
|
|
</p>
|
|
|
|
|
{/if}
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
{:else if report.failure}
|
|
|
|
|
<p class="state-word">Rechazada en el paso {report.failure.step}</p>
|
|
|
|
|
<p class="code">{report.failure.code}</p>
|
|
|
|
|
<p>{errorGloss(report.failure.code)}</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="when">
|
|
|
|
|
<p class="when-label">Fecha de apertura</p>
|
|
|
|
|
{#if report.unlock && unlockMs !== undefined}
|
|
|
|
|
<p class="date"><time datetime={report.unlock.rfc3339}>{formatDateTime(unlockMs, 'UTC')}</time></p>
|
|
|
|
|
<p>
|
|
|
|
|
En tu hora local{timeZone ? ` (${timeZone})` : ''}: {formatDateTime(unlockMs)}
|
|
|
|
|
</p>
|
|
|
|
|
<p class="muted">
|
|
|
|
|
Ronda {report.capsule?.round} de {report.profile?.network ?? report.capsule?.network}; {unlockMs <= nowMs
|
|
|
|
|
? `la fecha ya pasó, ${formatRelative(unlockMs, nowMs)}`
|
|
|
|
|
: `la fecha todavía no ha llegado: ${formatRelative(unlockMs, nowMs)}`}.
|
|
|
|
|
</p>
|
|
|
|
|
{:else if report.unlock}
|
|
|
|
|
<p class="date"><time datetime={report.unlock.rfc3339}>{report.unlock.rfc3339}</time></p>
|
|
|
|
|
{:else}
|
|
|
|
|
<p class="muted">
|
|
|
|
|
Sin calcular: sale de la DateKey en el paso 7, {report.steps[6]?.state === 'failed' ? 'que falló' : 'que no llegó a ejecutarse'}.
|
|
|
|
|
</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<section class="block" aria-labelledby="steps-title">
|
|
|
|
|
<h3 id="steps-title">Pasos 1 a 8</h3>
|
|
|
|
|
<StepList steps={report.steps} />
|
|
|
|
|
</section>
|
|
|
|
|
|
Phase 2, step 8: the open action of /inspect
After steps 1 to 8, a valid capsule whose date has passed on the device
clock can be opened in the page: steps 9 to 18 of spec section 63 with
open, loaded on demand with a dynamic import (opener.ts), so noble and
age-encryption stay out of the first load of every page.
- The release is supplied directly by the person (spec 63, step 10):
drand's JSON answer or the bare signature, pasted after opening the
drand URL the page links to, or the release in the record of an
official fixture. The page never fetches it and reads only its round
and signature (spec 11, 13). The CSP is unchanged.
- time_and_key credentials: a .dkk (readAccessKey reads at most
12 bytes + 16 MiB + 1) or age identities, one per line.
- The plaintext of the person's own file goes to a temporary OPFS file
(tempfile.ts), committed only after step 18 (spec 56), offered for
download and deleted on request, with another capsule, on pagehide
and, if left over, on the next visit. One directory and one Web Lock
per tab keep other tabs' clean-up away from files in use. Without
OPFS, or when the browser refuses it, capsules up to 64 MiB open in
memory. An opening in progress stops when another capsule is loaded.
- opening.ts builds the page model of steps 9 to 18 as the reference
records them; fixtures show their plaintext and compare its SHA-256
with their record.
- licenses.txt: the notices of tlock-js (ibe.ts) and age (bech32.ts),
the license of every package in the client bundle, Vite's and
rolldown's runtime code, and the site's own license. check-build now
fails if a notice is missing, or if a page loads noble, @scure/base
or age-encryption with its first load.
- The home page no longer says that the page never asks for keys.
Checked in the browser on the production build: the time_only,
time_and_key_portable (with its .dkk) and time_and_key_recipients (with
a pasted identity) fixtures open with the SHA-256 of their records; a
tampered signature fails at step 10 and a tampered STREAM chunk at step
17, with no download and no file left; an own file opens to OPFS,
downloads without a CSP violation and is deleted with its lock; a left
over directory goes on the next visit; no request leaves the origin.
An adversarial review (four dimensions, each finding checked by a
refuter) confirmed 15 findings, all fixed here.
2611 tests; coverage 100 % of the new modules, now a threshold.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
{@render opening?.()}
|
|
|
|
|
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
<div class="grid">
|
|
|
|
|
<section class="block" aria-labelledby="header-title">
|
|
|
|
|
<h3 id="header-title">Cabecera pública</h3>
|
|
|
|
|
{#if report.capsule}
|
|
|
|
|
{@const c = report.capsule}
|
|
|
|
|
<dl>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>capsule_id</dt>
|
|
|
|
|
<dd class="mono">{c.capsuleId}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>access_policy</dt>
|
|
|
|
|
<dd><span class="mono">{c.accessPolicy}</span> <span class="muted">{policyGloss(c.accessPolicy)}</span></dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>DateKey</dt>
|
|
|
|
|
<dd class="mono">{c.dateKey}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>DateKey decodificada</dt>
|
|
|
|
|
<dd class="mono">{c.dateKeyJSON}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Red (network)</dt>
|
|
|
|
|
<dd class="mono">{c.network}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Ronda</dt>
|
|
|
|
|
<dd class="mono">{c.round}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>unlock_at</dt>
|
|
|
|
|
<dd class="mono">{report.unlock?.rfc3339 ?? 'sin calcular'}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
</dl>
|
|
|
|
|
{:else}
|
|
|
|
|
<p class="muted">PUBLIC_HEADER no llegó a decodificarse.</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<section class="block" aria-labelledby="profile-title">
|
|
|
|
|
<h3 id="profile-title">Perfil fijado</h3>
|
|
|
|
|
{#if report.profile}
|
|
|
|
|
{@const p = report.profile}
|
|
|
|
|
<dl>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>profile_id</dt>
|
|
|
|
|
<dd class="mono">{p.id}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Proveedor y red</dt>
|
|
|
|
|
<dd><span class="mono">{p.provider}</span>, <span class="mono">{p.network}</span></dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Cadena (chain hash)</dt>
|
|
|
|
|
<dd class="mono">{p.chainHash}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Periodo</dt>
|
|
|
|
|
<dd>{p.period} s por ronda</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Génesis</dt>
|
|
|
|
|
<dd class="mono">{p.genesis}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Esquema</dt>
|
|
|
|
|
<dd class="mono">{p.scheme}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
</dl>
|
|
|
|
|
{:else if report.capsule}
|
|
|
|
|
<p class="muted">
|
|
|
|
|
La DateKey nombra el perfil <span class="mono">{report.capsule.network}</span>, que este lector no tiene fijado.
|
|
|
|
|
</p>
|
|
|
|
|
{:else}
|
|
|
|
|
<p class="muted">Se elige con la DateKey de PUBLIC_HEADER, que no llegó a decodificarse.</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<section class="block" aria-labelledby="prelude-title">
|
|
|
|
|
<h3 id="prelude-title">Prelude</h3>
|
|
|
|
|
{#if report.prelude}
|
|
|
|
|
{@const p = report.prelude}
|
|
|
|
|
<dl>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>Bytes</dt>
|
|
|
|
|
<dd class="mono">{p.hex}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
Read capsule format 2 of spec v0.9
Syncs testdata with datekeys-go at spec-v0.9 (7e2d83c) and moves the
reader to the DateKeys Protocol Specification v0.9. Both capsule formats
are read; a format 1 capsule keeps the verdict v0.8.2 gave it.
- framing: the VERSION of the prelude is the capsule format, 1 or 2
(Prelude.format, FORMAT_1, FORMAT_2, isFormat).
- control: decodeControl and encodeControl take the format; schema
version 2 adds payload_length (8 bytes, at most L_MAX) and padding
(1 or 2).
- padding.ts: the rules bloque256 and reforzado of spec §29.1, exact up
to L_MAX with BigInt bit lengths and ceil roundings, and the length of
PAYLOAD_AGE.
- open: exactly 16 stanzas in INNER_ACCESS_AGE of format 2 (step 12), P
at step 16, and at step 17 a plaintext of exactly P bytes whose
padding is zero; only the first L bytes are delivered, never the
padding. Step 17 is recorded when it passes, and step 18 gives the
bytes of content, as the reference does. Opened reports the format, L
and, in format 2, the rule and P.
- inspect: the JSON view carries format, as datekeys inspect -json.
- The page shows the format, warns about format 1, and gives the
padding rule and P once a format 2 capsule opens.
Tests: the twelve fixtures, the 125 mutation cases through open from
memory and from a Blob, the 4380 differential cases, padding.json, the
format 2 CBOR vectors, and padding.test.ts against a BigInt statement of
§29.1. The error texts of the 125 corpus cases were compared with
capsule.Open at spec-v0.9. ibe-vectors.json gains the seven format 2
fixtures from scripts/ibe-go-vectors.go; its frozen values are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
|
|
|
<dt>Marca y formato</dt>
|
|
|
|
|
<dd><span class="mono">{p.magic}</span>, formato {p.format}{p.format === 1 ? ', el de la v0.8.2' : ''}</dd>
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>FLAGS y RESERVED</dt>
|
|
|
|
|
<dd><span class="mono">{p.flags}</span>, <span class="mono">{p.reserved}</span></dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>PUBLIC_HEADER_LEN</dt>
|
|
|
|
|
<dd>{formatByteCount(p.publicHeaderLen)}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>SEALED_CONTROL_LEN</dt>
|
|
|
|
|
<dd>{formatByteCount(p.sealedControlLen)}</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>PAYLOAD_AGE</dt>
|
|
|
|
|
<dd>
|
|
|
|
|
desde el byte {formatInteger(p.payloadOffset)}{#if p.payloadLength !== undefined}, {formatByteCount(
|
|
|
|
|
p.payloadLength,
|
|
|
|
|
)}{:else}, fuera del fichero{/if}
|
|
|
|
|
</dd>
|
|
|
|
|
</div>
|
|
|
|
|
</dl>
|
|
|
|
|
{:else}
|
|
|
|
|
<p class="muted">El prelude no se superó.</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<section class="block" aria-labelledby="stanzas-title">
|
|
|
|
|
<h3 id="stanzas-title">Stanzas age</h3>
|
|
|
|
|
<dl>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>OUTER_TIME_AGE</dt>
|
|
|
|
|
<dd>
|
|
|
|
|
{#if report.outerStanzas}
|
|
|
|
|
{report.outerStanzas.length}
|
|
|
|
|
{report.outerStanzas.length === 1 ? 'stanza' : 'stanzas'}: <span class="mono">{stanzaTypes(report.outerStanzas)}</span>
|
|
|
|
|
<span class="muted">(se exige exactamente uno, tlock)</span>
|
|
|
|
|
{:else}
|
|
|
|
|
<span class="muted">sin leer</span>
|
|
|
|
|
{/if}
|
|
|
|
|
</dd>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<dt>PAYLOAD_AGE</dt>
|
|
|
|
|
<dd>
|
|
|
|
|
{#if report.payloadStanzas}
|
|
|
|
|
{report.payloadStanzas.length}
|
|
|
|
|
{report.payloadStanzas.length === 1 ? 'stanza' : 'stanzas'}: <span class="mono">{stanzaTypes(report.payloadStanzas)}</span>
|
|
|
|
|
<span class="muted">(se exige exactamente uno, X25519)</span>
|
|
|
|
|
{:else}
|
|
|
|
|
<span class="muted">sin leer</span>
|
|
|
|
|
{/if}
|
|
|
|
|
</dd>
|
|
|
|
|
</div>
|
|
|
|
|
</dl>
|
|
|
|
|
|
|
|
|
|
<h4 class="sub">Stanza tlock frente al perfil fijado</h4>
|
|
|
|
|
{#if report.tlock}
|
|
|
|
|
<ul class="compare">
|
|
|
|
|
{#each report.tlock as c (c.label)}
|
|
|
|
|
<li class={c.match ? 'match' : 'mismatch'}>
|
|
|
|
|
<p class="compare-head">
|
|
|
|
|
<span>{c.label}</span>
|
|
|
|
|
<span class="verdict-word">{comparisonState(c)}</span>
|
|
|
|
|
</p>
|
|
|
|
|
<p><span class="muted">En el stanza:</span> <span class="mono">{c.found ?? 'falta'}</span></p>
|
|
|
|
|
<p><span class="muted">Esperado:</span> <span class="mono">{c.expected}</span></p>
|
|
|
|
|
</li>
|
|
|
|
|
{/each}
|
|
|
|
|
</ul>
|
|
|
|
|
{:else if report.outerStanzas}
|
|
|
|
|
<p class="muted">OUTER_TIME_AGE no trae ningún stanza tlock.</p>
|
|
|
|
|
{:else}
|
|
|
|
|
<p class="muted">Se compara cuando se leen la cabecera, el perfil y OUTER_TIME_AGE.</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</section>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<section class="block" aria-labelledby="ext-title">
|
|
|
|
|
<h3 id="ext-title">Extensiones de PUBLIC_HEADER</h3>
|
|
|
|
|
<p class="prose muted">
|
|
|
|
|
Este inspector implementa el protocolo base V1 y no conoce ninguna extensión: una crítica hace fallar el paso 4 y
|
|
|
|
|
las no críticas se ignoran. Sus datos son bytes opacos para el protocolo.
|
|
|
|
|
</p>
|
|
|
|
|
{#if report.extensions}
|
|
|
|
|
<ExtensionList extensions={report.extensions} />
|
|
|
|
|
{:else}
|
|
|
|
|
<p class="muted">PUBLIC_HEADER no llegó a decodificarse.</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<section class="block" aria-labelledby="json-title">
|
|
|
|
|
<h3 id="json-title">Salida de la CLI</h3>
|
|
|
|
|
<details bind:open={jsonOpen}>
|
|
|
|
|
<summary>JSON de <code>datekeys inspect -json</code></summary>
|
|
|
|
|
{#if shownJSON !== report.json}
|
|
|
|
|
<p class="json-note">
|
|
|
|
|
Los caracteres invisibles o de control se muestran escapados (<code>\uXXXX</code>, el mismo JSON).
|
|
|
|
|
<strong>Copiar JSON</strong> copia la salida exacta de la CLI.
|
|
|
|
|
</p>
|
|
|
|
|
{/if}
|
|
|
|
|
<pre class="json">{shownJSON}</pre>
|
|
|
|
|
</details>
|
|
|
|
|
</section>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
/* minmax(0, 1fr): a child's unbreakable content must not widen the track
|
|
|
|
|
beyond the screen. */
|
|
|
|
|
.report {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(0, 1fr);
|
|
|
|
|
gap: 2.5rem;
|
|
|
|
|
}
|
|
|
|
|
.report-head {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
align-items: flex-end;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 1rem 2rem;
|
|
|
|
|
padding-bottom: 1rem;
|
|
|
|
|
border-bottom: 1px solid var(--rule);
|
|
|
|
|
}
|
|
|
|
|
.file h2 {
|
|
|
|
|
font-family: var(--mono);
|
|
|
|
|
font-size: var(--t-h2);
|
|
|
|
|
font-weight: 650;
|
|
|
|
|
letter-spacing: 0;
|
|
|
|
|
overflow-wrap: anywhere;
|
|
|
|
|
}
|
|
|
|
|
.file p {
|
|
|
|
|
margin-top: 0.25rem;
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
}
|
|
|
|
|
.copy {
|
|
|
|
|
display: grid;
|
|
|
|
|
justify-items: end;
|
|
|
|
|
gap: 0.25rem;
|
|
|
|
|
}
|
|
|
|
|
.copy-status {
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
color: var(--ink-muted);
|
|
|
|
|
min-height: 1.3em;
|
|
|
|
|
text-align: right;
|
|
|
|
|
max-width: 28rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The verdict: the one loud moment of the page. */
|
|
|
|
|
.verdict {
|
|
|
|
|
display: grid;
|
|
|
|
|
border: 1px solid var(--rule);
|
|
|
|
|
border-top: 6px solid var(--state);
|
|
|
|
|
border-radius: var(--radius);
|
|
|
|
|
background: var(--paper-2);
|
|
|
|
|
}
|
|
|
|
|
.verdict.valid {
|
|
|
|
|
--state: var(--pass);
|
|
|
|
|
}
|
|
|
|
|
.verdict.invalid {
|
|
|
|
|
--state: var(--fail);
|
|
|
|
|
}
|
|
|
|
|
@media (min-width: 820px) {
|
|
|
|
|
.verdict {
|
|
|
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
|
|
|
|
|
}
|
|
|
|
|
.when {
|
|
|
|
|
border-top: 0;
|
|
|
|
|
border-left: 1px solid var(--rule);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.state,
|
|
|
|
|
.when {
|
|
|
|
|
padding: 1.25rem 1.25rem 1.5rem;
|
|
|
|
|
display: grid;
|
|
|
|
|
align-content: start;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
.when {
|
|
|
|
|
border-top: 1px solid var(--rule);
|
|
|
|
|
}
|
Read capsule format 2 of spec v0.9
Syncs testdata with datekeys-go at spec-v0.9 (7e2d83c) and moves the
reader to the DateKeys Protocol Specification v0.9. Both capsule formats
are read; a format 1 capsule keeps the verdict v0.8.2 gave it.
- framing: the VERSION of the prelude is the capsule format, 1 or 2
(Prelude.format, FORMAT_1, FORMAT_2, isFormat).
- control: decodeControl and encodeControl take the format; schema
version 2 adds payload_length (8 bytes, at most L_MAX) and padding
(1 or 2).
- padding.ts: the rules bloque256 and reforzado of spec §29.1, exact up
to L_MAX with BigInt bit lengths and ceil roundings, and the length of
PAYLOAD_AGE.
- open: exactly 16 stanzas in INNER_ACCESS_AGE of format 2 (step 12), P
at step 16, and at step 17 a plaintext of exactly P bytes whose
padding is zero; only the first L bytes are delivered, never the
padding. Step 17 is recorded when it passes, and step 18 gives the
bytes of content, as the reference does. Opened reports the format, L
and, in format 2, the rule and P.
- inspect: the JSON view carries format, as datekeys inspect -json.
- The page shows the format, warns about format 1, and gives the
padding rule and P once a format 2 capsule opens.
Tests: the twelve fixtures, the 125 mutation cases through open from
memory and from a Blob, the 4380 differential cases, padding.json, the
format 2 CBOR vectors, and padding.test.ts against a BigInt statement of
§29.1. The error texts of the 125 corpus cases were compared with
capsule.Open at spec-v0.9. ibe-vectors.json gains the seven format 2
fixtures from scripts/ibe-go-vectors.go; its frozen values are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
|
|
|
.format-note {
|
|
|
|
|
padding: 0.5rem 0.75rem;
|
|
|
|
|
border-radius: var(--radius);
|
|
|
|
|
background: var(--caution-bg);
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
}
|
Inspector page: static SvelteKit site with /inspect (plan step 5)
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
|
|
|
.state-word {
|
|
|
|
|
font-size: var(--t-h2);
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
letter-spacing: -0.015em;
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
color: var(--state);
|
|
|
|
|
}
|
|
|
|
|
.code {
|
|
|
|
|
font-family: var(--mono);
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
overflow-wrap: anywhere;
|
|
|
|
|
}
|
|
|
|
|
.when-label {
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: var(--ink-muted);
|
|
|
|
|
}
|
|
|
|
|
.date {
|
|
|
|
|
font-size: var(--t-date);
|
|
|
|
|
font-weight: 650;
|
|
|
|
|
line-height: 1.15;
|
|
|
|
|
letter-spacing: -0.02em;
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
text-wrap: balance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.block {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(0, 1fr);
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
align-content: start;
|
|
|
|
|
}
|
|
|
|
|
.grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(0, 1fr);
|
|
|
|
|
gap: 2.5rem 3rem;
|
|
|
|
|
}
|
|
|
|
|
@media (min-width: 900px) {
|
|
|
|
|
.grid {
|
|
|
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dl {
|
|
|
|
|
display: grid;
|
|
|
|
|
border-top: 1px solid var(--rule);
|
|
|
|
|
}
|
|
|
|
|
dl > div {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 0.1rem 1rem;
|
|
|
|
|
padding-block: 0.55rem;
|
|
|
|
|
border-bottom: 1px solid var(--rule);
|
|
|
|
|
}
|
|
|
|
|
@media (min-width: 560px) {
|
|
|
|
|
dl > div {
|
|
|
|
|
grid-template-columns: 11rem minmax(0, 1fr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dt {
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: var(--ink-muted);
|
|
|
|
|
overflow-wrap: anywhere;
|
|
|
|
|
}
|
|
|
|
|
dd {
|
|
|
|
|
margin: 0;
|
|
|
|
|
overflow-wrap: anywhere;
|
|
|
|
|
}
|
|
|
|
|
dd.mono,
|
|
|
|
|
dd .mono {
|
|
|
|
|
font-size: 0.85rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sub {
|
|
|
|
|
font-size: var(--t-body);
|
|
|
|
|
margin-top: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
.compare {
|
|
|
|
|
list-style: none;
|
|
|
|
|
padding: 0;
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 0.6rem;
|
|
|
|
|
}
|
|
|
|
|
.compare li {
|
|
|
|
|
padding: 0.6rem 0.75rem;
|
|
|
|
|
border-left: 3px solid var(--pass);
|
|
|
|
|
background: var(--paper-2);
|
|
|
|
|
border-radius: 0 var(--radius) var(--radius) 0;
|
|
|
|
|
overflow-wrap: anywhere;
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
}
|
|
|
|
|
.compare li.mismatch {
|
|
|
|
|
border-left-color: var(--fail);
|
|
|
|
|
background: var(--fail-bg);
|
|
|
|
|
}
|
|
|
|
|
.compare-head {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
font-size: var(--t-body);
|
|
|
|
|
}
|
|
|
|
|
.compare .verdict-word {
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
color: var(--pass);
|
|
|
|
|
}
|
|
|
|
|
.compare li.mismatch .verdict-word {
|
|
|
|
|
color: var(--fail);
|
|
|
|
|
}
|
|
|
|
|
.compare .mono {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
details summary {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
width: fit-content;
|
|
|
|
|
padding-block: 0.25rem;
|
|
|
|
|
}
|
|
|
|
|
.json-note {
|
|
|
|
|
margin-top: 0.75rem;
|
|
|
|
|
font-size: var(--t-small);
|
|
|
|
|
color: var(--ink-muted);
|
|
|
|
|
max-width: var(--measure);
|
|
|
|
|
}
|
|
|
|
|
.json {
|
|
|
|
|
margin-top: 0.75rem;
|
|
|
|
|
padding: 0.85rem 1rem;
|
|
|
|
|
background: var(--paper-2);
|
|
|
|
|
border: 1px solid var(--rule);
|
|
|
|
|
border-radius: var(--radius);
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
overflow-wrap: anywhere;
|
|
|
|
|
}
|
|
|
|
|
</style>
|