From afa21289535b98186fa7f4b299769db80c51ee02 Mon Sep 17 00:00:00 2001 From: sergeych Date: Mon, 17 Aug 2026 02:23:01 +0400 Subject: [PATCH] Preserve first-session design context --- README.md | 1 + SESSION_NOTES.md | 273 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 SESSION_NOTES.md diff --git a/README.md b/README.md index 8c4428b..263dd8e 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ And its project motto keeps the same principle courteous: ## Project documents - [Wake-up point and roadmap](ROADMAP.md) +- [First-session continuity notes](SESSION_NOTES.md) - [Coarse-grained concept](CONCEPT.md) - [Architecture decisions](ARCHITECTURE.md) - [Certificate Investigator design](DESIGN.md) diff --git a/SESSION_NOTES.md b/SESSION_NOTES.md new file mode 100644 index 0000000..d874019 --- /dev/null +++ b/SESSION_NOTES.md @@ -0,0 +1,273 @@ +# Session continuity notes + +These notes preserve the context of Browsec's first design and implementation +session. Read this file together with [`ROADMAP.md`](ROADMAP.md), then consult +the detailed concept and architecture documents only as needed. + +## People and repository + +- Project creator: **sergeych** (`sergeych `). +- AI design and implementation collaborator: **Codex (OpenAI)**. +- Repository: `ssh://git@gitea.sergeych.net:2291/SergeychWorks/browsec.git`. +- Main branch: `main`. +- The repository was clean and fully pushed when these notes were written. +- Work was intentionally committed in small conceptual milestones. + +## Why the project exists + +The starting problem is that conventional browser TLS trust is governed by a +global authority model that users cannot meaningfully replace or refine. A user +may need to investigate broken certificates, trust a precise local certificate +or CA, distrust an otherwise globally accepted authority, and eventually use +community trust without surrendering the final decision to another central +operator. + +The intended browser is a genuinely independent Firefox downstream. Chromium +was considered but rejected as a poorer base for the project's independence and +governance goals. TrustLab exists so the security model can be developed and +tested browserlessly before modifying Firefox NSS/PSM. + +The primary scope remains TLS trust substitution. The plugin API should not grow +into a general browser-extension “Swiss army knife” until that narrow security +problem is sound. + +## Naming and character + +- **Browsec**: the browser project. +- **Velvet Hammer**: the trust engine. +- **TrustLab**: the browser-neutral research and diagnostic tool. +- **Browsec Trust API**: the strict plugin contract. + +The engine name expresses a deliberate combination: a calm and comprehensible +surface around rigid security boundaries. The proposed emblem is a restrained, +polished spherical hammer head with a short handle, possibly meeting a +certificate-chain link. + +Project language established during the session includes *Velvet verdict*, +*Hammer rule*, and *TrustLab powered by Velvet Hammer*. + +Two sentences capture the project's temperament: + +> The hammer permits no silent widening of scope. + +> If one must be struck by security policy, let it be by a respectable velvet +> hammer: precise, accountable, and courteous enough to explain why. + +## Core design decisions + +### The plugin chain contains the decision + +There is no hidden “browser god” outside the plugin chain making an unexplained +final trust choice. The immutable Browsec final handler is itself the final +plugin and cannot be removed or replaced. This keeps the model compositionally +honest while preserving a fail-closed terminus. + +Every configured plugin has one explicit role: + +- observer; +- advisor; +- decision authority; +- veto authority. + +Roles are local configuration, not powers self-declared by plugin packages. +Plugins may contribute evidence, warnings, and advisory votes as appropriate, +but only explicitly authorized roles can return terminal Boolean verdicts. + +### Facts, interpretation, and decisions remain separate + +The TLS connection produces immutable facts. Plugins append attributed entries +to a journal; they cannot rewrite the facts or previous entries. A terminal +verdict references the journal entries supporting it. + +The final trust boundary is Boolean. Nuance and uncertainty remain visible in +evidence and votes rather than producing an ambiguous terminal value. + +### Scope is explicit and rigid + +A verdict declares: + +- `trusted: true | false`; +- exact certificate-for-host or exact DER authority-for-host scope; +- port scope; +- optional subdomain scope for an authority; +- connection, session, timed, or persistent lifetime; +- supporting journal entries; +- the exact TLS errors it overrides. + +“Trust once” was rejected as ambiguous terminology. The implementation uses +explicit connection and session lifetimes. + +An authority rule identifies the SHA-256 fingerprint of the exact DER CA +certificate, not merely a subject name or public key. The CA must occur in the +active chain, have DER-confirmed Basic Constraints, permit `keyCertSign`, and +contain no unsupported critical extensions. Authority trust may repair only +trust-anchor failures; it cannot excuse expiry, hostname mismatch, signature +failure, or another independent error. + +Local distrust has precedence over matching local trust. + +### Interactive and background work + +`onBeforeTlsAccept` is deliberately synchronous and fast. It may use already +available local state but cannot wait for network or UI. + +Failed navigation is handled through asynchronous `onTlsFailure`, where an +authorized plugin may present clearly browser-owned UI and then request a fresh +connection retry. Background evidence collection is independent of the fast +success path. + +Plugins may eventually perform community or peer-to-peer background work, but +those mechanisms do not receive implicit decision authority. + +### Security UI cannot look like web content + +The future browser-owned decision surface must be unmistakably distinct from +ordinary pages and extension content. TrustLab currently simulates this with a +fixed security frame and synthetic/live/offline seals. This distinction must be +implemented with stronger browser chrome when Firefox integration begins. + +## What was implemented + +### Trust runtime + +- Strict TypeScript API version `0.1`. +- Dependency-free JavaScript reference runner. +- Immutable normalized TLS facts. +- Append-only attributed journal. +- Plugin timeouts, mode enforcement, and immutable final handler. +- In-memory scoped policy overlay exposed as an ordinary plugin. +- Connection/session/timed/persistent rules and explicit rule history. + +### Live TLS microscope + +From `trustlab/`: + +```sh +npm run probe -- example.com +npm run probe -- expired.badssl.com --json +npm run ui +``` + +The read-only probe records TLS protocol and cipher, conventional OpenSSL trust, +certificate DER/SPKI fingerprints, identities, dates, signatures, normalized +failure categories, and observed-chain caveats. It never modifies a trust store. + +The local UI server binds to `127.0.0.1`, accepts a small same-origin JSON POST, +and enforces a ten-second probe timeout. A browser can enter a live hostname and +use the same TrustLab plugin chain and diagnostic UI as synthetic fixtures. + +Node/OpenSSL does not expose a reliable boundary between server-sent +certificates and certificates added during construction. The current report +therefore labels its chain as an observed peer chain and duplicates it into the +API's presented/constructed fields rather than pretending certainty. + +### DER explorer + +The browser-compatible DER reader is dependency-free and enforces definite, +minimal lengths, container boundaries, node-count limits, and nesting limits. +It retains a byte-offset tree and every extension's original bytes. + +Implemented semantic decoders include: + +- Basic Constraints; +- Key Usage; +- Extended Key Usage OIDs; +- Subject Key Identifier; +- Authority Key Identifier; +- Subject Alternative Name DNS/IP/email/URI forms. + +The UI synchronizes ASN.1 nodes with hexadecimal bytes in both directions and +allows original `.der` export. Recognizing an extension's name is intentionally +different from supporting its semantics; an unsupported critical extension +fails closed even if its OID has a friendly label. + +### Explainable path construction + +The live probe evaluates every possible issuer pair among observed certificates +and records: + +- issuer/subject match; +- cryptographic signature verification; +- AKI/SKI match when both identifiers exist; +- issuer CA and signing eligibility; +- critical-extension blockers. + +It enumerates acyclic candidate paths and independently records structural +termination, provider-attributed trust, validity failures, and path-length +constraint violations. Thus “where a path goes” is distinct from “whether the +path is valid” and “who trusts its terminus.” + +### Offline investigation bundles + +Versioned `.browsec-investigation.json` files include original public DER, +facts, findings, path analysis, decision journal, verdict, and policy history. +They explicitly declare that no private keys or TLS session secrets are present. + +Import is capped at 10 MiB, reparses DER, recomputes SHA-256 fingerprints, and +rebuilds DER-derived CA, Key Usage, critical-extension, SAN, SKI, and AKI facts. +Imported verdicts and policy remain historical evidence and are not activated. + +## Verification at handoff + +The last complete local verification passed: + +```sh +cd trustlab +npm test +npm run check +npm run build +``` + +There were **38 passing tests**. Live checks also behaved as intended: + +- `example.com`: one structurally and cryptographically valid path, attributed + to the Node/OpenSSL conventional-validation terminus. +- `expired.badssl.com`: a structurally linked path independently marked invalid + because two exact certificates were expired. + +Use `git status --short` before new work. Existing uncommitted changes, if any, +must be treated as belonging to the user. + +## Exact next implementation seam + +Implement named trust providers before adding more global policy behavior. + +Start with a strict TypeScript contract that accepts a candidate path and +immutable certificate facts, then returns an attributed Boolean recognition or +distrust result containing: + +- provider ID and human name; +- provider kind; +- snapshot ID/version; +- observation or effective time; +- exact recognized/distrusted anchor fingerprint; +- supporting reason codes. + +Build two browserless reference providers first: + +1. An explicit in-memory anchor set. +2. An explicit local distrust set. + +Evaluate them independently against each candidate path. Do not union provider +stores, do not collapse conflicting results, and do not change final-decision +semantics yet. Show a comparison matrix in TrustLab and preserve provider +snapshots in investigation bundles. + +After that, add safe PEM/DER anchor collection import with duplicate detection. +Only later add real Mozilla/OS adapters, AIA issuer retrieval, Name Constraints, +revocation, Certificate Transparency, historical comparisons, durable policy, +and Firefox NSS/PSM integration. + +## Files to open first next session + +1. [`ROADMAP.md`](ROADMAP.md) +2. [`trustlab/sdk/plugin-api.ts`](trustlab/sdk/plugin-api.ts) +3. [`trustlab/src/path-analysis.js`](trustlab/src/path-analysis.js) +4. [`trustlab/src/der-explorer.js`](trustlab/src/der-explorer.js) +5. [`trustlab/src/investigation-bundle.js`](trustlab/src/investigation-bundle.js) +6. [`trustlab/ui/app.js`](trustlab/ui/app.js) + +The conceptual documents remain authoritative for broader intent: +[`CONCEPT.md`](CONCEPT.md), [`ARCHITECTURE.md`](ARCHITECTURE.md), and +[`DESIGN.md`](DESIGN.md). +