Files
beardrive/architecture/overview.md
T
Snow Lee (Sungwon)andGitHub a3dfa73fef Catch a credential when it syncs, not only when you share it (#162)
* refactor(secrets): lift the share-time credential rules into internal/secrets

The rules only ever ran on the rarest path a file takes. Moving them out of
internal/webapp is what lets internal/syncer run the same six rules on the
path every file takes, without inverting the dependency.

Pure move plus one addition: Label(), the six human strings that until now
lived only in the frontend's SECRET_LABELS — so 'bdrive share' stops printing
a bare rule id where the web dialog says 'an AWS access key'. Rule ids and the
rule/line JSON tags are unchanged: Browser.tsx keys off them, so they are a
wire contract.

* feat(sync): warn when a synced file looks like it holds a credential

The six share-time rules now run on the path every file takes. A file with an
AWS key in it used to ride a normal sync to the hub, to every teammate's disk
and into every future agent's context with no badge and no warning — while the
Share dialog one click later blocked that exact file.

Warn, never block: the op is journaled and pushed exactly as before. A hold arm
would mean a false positive silently parks someone's changes, and it would
break the cycle's degrade-to-offline posture.

- scan() reads the blob PutBlobFile just wrote (the bytes that were actually
  journaled), only on the branches that wrote one — an unchanged file is still
  never re-read.
- Findings persist per path in secrets-<mount>.json, merged rather than
  replaced: nearly every cycle scans zero files, and a whole-set rewrite would
  erase the warning seconds after it appeared. Fixing the file clears it.
- bdrive status grows a secrets block; the agent hook appends one advisory
  sentence. Rule ids and line numbers only, never the matched bytes.
- SaveSecrets failing logs and continues: advisory telemetry never gets a veto
  over convergence.

* docs: the credential check now runs on sync, not only on share

README, the CLI reference and project-files get the new bdrive status block
and the warn-never-block posture, with the three limits stated (checked when
it changes, first 1 MiB, writing device only). Diagrams: internal/secrets is a
package of its own in the overview, secretLog joins the sync engine, and the
share-gate class notes that it no longer owns the rules.

* test(sync): assert an unchanged file is never re-read for credentials

The check must ride the branch that already reads the file. Clearing the record
by hand and cycling proves it: a scan that re-read unchanged files would put the
finding back, and the daemon's 3-second tick would pay for it on every file.
2026-08-18 15:08:44 -07:00

2.8 KiB

BearDrive — system overview

The whole repo on one page: every package and surface, and which detail diagram drills into it. Reflects the code as of this commit; update this file in any PR that adds/removes a package or changes how the pieces connect. Detail diagrams: cli-sync.md, webapp-server.md, webapp-frontend.md.

flowchart LR
    subgraph device["User device"]
        wf["working folder<br/>(real files + .bdrive/config.json)"]
        cli["cmd/bdrive<br/>CLI commands"]
        dmn["internal/daemon<br/>background loop"]
        eng["internal/syncer Session.Cycle<br/>internal/journal ops + replay"]
        vs["volume store ~/.bdrive/volumes/id<br/>internal/store: blobs, journals,<br/>state, paused marker"]
        cfg["internal/config<br/>device.json, settings.json, mounts.json"]
    end

    subgraph agents["Agent platforms (claude / codex / gemini / hermes)"]
        hooks["internal/agenthooks<br/>turn-boundary sync hooks"]
    end

    subgraph hub["bdrive serve hub"]
        srv["internal/webapp Server<br/>auth, orgs, projects, shares,<br/>history, read heat, store proxy"]
        fe["webapp/frontend React SPA<br/>committed dist go:embed'ed at webapp/static"]
        meta["MetaStore: file JSON (default)<br/>or sqlite / postgres (db_sql)"]
    end

    store["object store (hub-owned)<br/>internal/remote: file:// s3:// gs://<br/>blobs + per-device journals"]

    tpl["internal/templates<br/>go:embed'ed starting structures<br/>(docs, wiki, para, skills: skeleton + AGENTS.md)"]

    sec["internal/secrets<br/>six credential rules, stdlib only<br/>shared by the share gate and the sync scan"]

    docs["web/docs — docs.beardrive.ai<br/>Astro/Starlight, deploys separately"]
    cloud["cloud/ (PRIVATE nested repo, gitignored)<br/>managed beardrive.ai: swaps AuthProvider,<br/>QuotaProvider, MetaStore seams"]

    wf <-->|scan / materialize| eng
    cli --> eng
    dmn --> eng
    cli --> cfg
    eng --> vs
    eng <-->|"https:// backend (internal/remote/http.go)<br/>device token, /api/p/id/store/*"| srv
    hooks -->|"bdrive sync --hook / --note, read-log<br/>gated: enrolled + not paused"| cli
    srv --> store
    srv --> meta
    eng -->|"scan: warn, never hold"| sec
    srv -->|"share mint: refuse"| sec
    cli -->|"init --template: seed locally"| tpl
    srv -->|"POST /api/projects template:<br/>seed as ops under the hub's device"| tpl
    fe -->|/api/config, /api/projects, viewer APIs| srv
    cloud -.->|imports OSS packages,<br/>replaces providers| srv
    docs -.->|documents| cli

Not drawn in any detail diagram (deliberately): web/docs (content site, no Go/TS application code) and cloud/ (private repo — its architecture lives there; here it only consumes the provider seams drawn in webapp-server.md).