Preserve first-session design context

This commit is contained in:
Sergey Chernov 2026-08-17 02:23:01 +04:00
parent d22dbcbb72
commit 7b1ffc4fd5
2 changed files with 274 additions and 0 deletions

View File

@ -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)

273
SESSION_NOTES.md Normal file
View File

@ -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 <real.sergeych@gmail.com>`).
- 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).