Preserve first-session design context
This commit is contained in:
parent
d22dbcbb72
commit
7b1ffc4fd5
@ -47,6 +47,7 @@ And its project motto keeps the same principle courteous:
|
|||||||
## Project documents
|
## Project documents
|
||||||
|
|
||||||
- [Wake-up point and roadmap](ROADMAP.md)
|
- [Wake-up point and roadmap](ROADMAP.md)
|
||||||
|
- [First-session continuity notes](SESSION_NOTES.md)
|
||||||
- [Coarse-grained concept](CONCEPT.md)
|
- [Coarse-grained concept](CONCEPT.md)
|
||||||
- [Architecture decisions](ARCHITECTURE.md)
|
- [Architecture decisions](ARCHITECTURE.md)
|
||||||
- [Certificate Investigator design](DESIGN.md)
|
- [Certificate Investigator design](DESIGN.md)
|
||||||
|
|||||||
273
SESSION_NOTES.md
Normal file
273
SESSION_NOTES.md
Normal 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).
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user