docs: add architecture overview - #1360
Conversation
Add ARCHITECTURE.md, a contributor-facing map of the codebase that correlates this CLI with the wider Notary Project: - Where notation sits relative to notaryproject/specifications and the notation-go / notation-core-go / tspclient-go / plugin-framework libraries, with the exact versions pinned in go.mod. - A specification map linking each Notary Project spec to the parts of the CLI it governs. - Mermaid diagrams for the layering, sign/verify workflows, trust model, OCI signature storage (referrers), plugin invocation, and CI/CD. The specifications remain the source of truth; this document is a map for contributors, not a restatement of normative behaviour. Package- and symbol-level detail is deliberately left to godoc so the doc does not drift from the code. Link it from README.md and building.md. Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>
There was a problem hiding this comment.
Pull request overview
Adds a contributor-facing architecture map for the Notation CLI, and links to it from existing contributor documentation, to help new contributors understand how this repo relates to the wider Notary Project.
Changes:
- Add
ARCHITECTURE.mdwith an overview of project layering, key workflows, trust model, and related Notary Project specs/libraries. - Link
ARCHITECTURE.mdfromREADME.md(contributing section) andbuilding.md(developer onboarding).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
README.md |
Adds a link to the new architecture overview doc for contributors. |
building.md |
Adds a pointer to ARCHITECTURE.md for readers who want codebase orientation. |
ARCHITECTURE.md |
Introduces a comprehensive architecture overview (diagrams, spec map, workflows, dev workflow). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1360 +/- ##
=======================================
Coverage 79.09% 79.09%
=======================================
Files 68 68
Lines 3076 3076
=======================================
Hits 2433 2433
Misses 436 436
Partials 207 207 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Signing keys live in signingkeys.json with key material under localkeys/, not config.json. Confirmed against dir.PathSigningKeys and dir.LocalKeysDir in notation-go. - Fully qualify notation.BlobVerifier to match notation.BlobSigner. - Prefix fix-line-endings with 'make' for consistency with the other entries in the table. Signed-off-by: Tatsat Mishra <tamishra@microsoft.com>
shizhMSFT
left a comment
There was a problem hiding this comment.
The doc should be non-verbose, simplified, and de-duplicated.
| SPEC("<b>notaryproject/specifications</b><br/>normative behaviour<br/>signature · trust policy · workflows · plugins") | ||
| CLI("<b>notation</b> (this repo)<br/>Cobra CLI · flags · output rendering") | ||
| NG("<b>notation-go</b><br/>signer · verifier · trust policy<br/>trust store · plugin manager · registry") | ||
| NCG("<b>notation-core-go</b><br/>signature envelopes (JWS · COSE)<br/>x509 · revocation (CRL/OCSP)") | ||
| TSP("<b>tspclient-go</b><br/>RFC 3161 timestamping") | ||
| PFW("<b>notation-plugin-framework-go</b><br/>plugin contract") | ||
| ORAS("<b>oras-go/v2</b><br/>OCI registry & OCI-layout I/O") | ||
| PLUGIN("Third-party plugins<br/>KMS / HSM signing binaries") |
There was a problem hiding this comment.
Consider remove descriptions like "normative behaviour signature · trust policy · workflows · plugins" as they are too verbose for a diagram.
| | Dependency | Version in [`go.mod`](go.mod) | Role | | ||
| |---|---|---| | ||
| | [`notation-go`](https://github.com/notaryproject/notation-go) | `v1.2.0-beta.1.0.20250512015818-2bc67e7695ef` | Signing/verification engine, trust policy & trust store evaluation, plugin manager, registry glue | | ||
| | [`notation-core-go`](https://github.com/notaryproject/notation-core-go) | `v1.3.0` | Signature envelope generation/parsing (JWS, COSE), certificate chain validation, CRL/OCSP revocation | | ||
| | [`notation-plugin-framework-go`](https://github.com/notaryproject/notation-plugin-framework-go) | `v1.0.0` | Contract shared with out-of-process plugin binaries | | ||
| | [`tspclient-go`](https://github.com/notaryproject/tspclient-go) | `v1.0.1-0.20250306063739-4f55b14d9f01` | RFC 3161 Time-Stamp Protocol client | | ||
| | [`oras-go/v2`](https://oras.land) | `v2.6.0` | OCI registry client, registry auth, OCI image layout I/O | |
There was a problem hiding this comment.
It is better to remove versions as they are not tracked by dependabot in markdown files..
| ## High-Level Architecture | ||
|
|
||
| ```mermaid | ||
| flowchart TD | ||
| A("CLI layer<br/><b>cmd/notation/</b><br/>sign · verify · list · inspect · login · key<br/>+ blob/ · cert/ · plugin/ · policy/") | ||
| B("CLI-internal<br/><b>cmd/notation/internal/</b><br/>flag · display · sign · verify<br/>truststore · experimental · errors · plugin") | ||
| C("Shared utilities<br/><b>internal/</b><br/>auth · config · envelope<br/>httputil · revocation · x509") | ||
| D("External Notary libraries<br/>notation-go · notation-core-go · oras-go") | ||
|
|
||
| A -->|"delegates to"| B | ||
| B -->|"built on"| C | ||
| B -->|"calls"| D | ||
|
|
||
| classDef cli fill:#dbeafe,stroke:#1d4ed8,stroke-width:1.5px,color:#1e3a8a; | ||
| classDef internal fill:#fef3c7,stroke:#b45309,stroke-width:1.5px,color:#78350f; | ||
| classDef utils fill:#dcfce7,stroke:#15803d,stroke-width:1.5px,color:#14532d; | ||
| classDef libs fill:#f3e8ff,stroke:#7e22ce,stroke-width:1.5px,color:#581c87; | ||
|
|
||
| class A cli | ||
| class B internal | ||
| class C utils | ||
| class D libs | ||
| ``` |
There was a problem hiding this comment.
This section duplicates the section "Where Notation Sits in the Notary Project".
| ### Signing (`runSign`, [`cmd/notation/sign.go`](cmd/notation/sign.go)) | ||
|
|
||
| ```mermaid | ||
| flowchart LR | ||
| A("GetSigner<br/>local key or plugin") --> B("getRepository<br/>registry or OCI layout") | ||
| B --> C("prepareSigningOpts<br/>envelope · expiry · TSA · revocation") | ||
| C --> D("resolveReference<br/>tag → digest") | ||
| D --> E("notation.SignOCI<br/>pushes signature as OCI referrer") | ||
|
|
||
| classDef step fill:#dbeafe,stroke:#1d4ed8,stroke-width:1.5px,color:#1e3a8a; | ||
| class A,B,C,D,E step | ||
| ``` | ||
|
|
||
| Signing always resolves a tag to an immutable digest first, so a signature is bound to specific content rather than a movable tag. | ||
|
|
||
| ### Verification (`runVerify`, [`cmd/notation/verify.go`](cmd/notation/verify.go)) | ||
|
|
||
| ```mermaid | ||
| flowchart LR | ||
| A("GetVerifier<br/>trust store · trust policy<br/>revocation · plugins") --> B("getRepository +<br/>resolveReference") | ||
| B --> C("notation.Verify") | ||
| C -->|"failure"| D("ComposeVerification<br/>FailurePrintout") | ||
| C --> E("display handler<br/>tree · json · text") | ||
| D --> E | ||
|
|
||
| classDef step fill:#dcfce7,stroke:#15803d,stroke-width:1.5px,color:#14532d; | ||
| classDef fail fill:#fee2e2,stroke:#b91c1c,stroke-width:1.5px,color:#7f1d1d; | ||
| class A,B,C,E step | ||
| class D fail | ||
| ``` | ||
|
|
||
| Blob commands mirror both flows using `notation.BlobSigner` / `notation.BlobVerifier` against local files instead of a registry. |
There was a problem hiding this comment.
Same here. Remove verbose descriptions for diagrams.
| ```mermaid | ||
| flowchart TD | ||
| CFG("Notation config directory") | ||
| TS("<b>Trust store</b><br/>truststore/x509/{ca,signingAuthority,tsa}/<store>/<br/>managed by <code>notation cert</code>") | ||
| TP("<b>Trust policy</b><br/>trustpolicy.oci.json · trustpolicy.blob.json<br/>managed by <code>notation policy</code> / <code>notation blob policy</code>") | ||
| KEY("<b>Signing keys</b><br/>signingkeys.json + localkeys/<br/>managed by <code>notation key</code>") | ||
|
|
||
| CFG --> TS | ||
| CFG --> TP | ||
| CFG --> KEY | ||
| TP -->|"selects"| TS | ||
|
|
||
| classDef root fill:#e0e7ff,stroke:#4338ca,stroke-width:2px,color:#312e81; | ||
| classDef leaf fill:#dcfce7,stroke:#15803d,stroke-width:1.5px,color:#14532d; | ||
| class CFG root | ||
| class TS,TP,KEY leaf | ||
| ``` |
There was a problem hiding this comment.
Same here. Remove verbose descriptions for diagrams.
Description
Adds
ARCHITECTURE.md— a contributor-facing map of the codebase that explicitly correlates this CLI with the wider Notary Project — and links it fromREADME.mdandbuilding.md.This is documentation only: no source, CLI, dependency, or Go-version changes.
What's in the document
notaryproject/specificationsand tonotation-go,notation-core-go,notation-plugin-framework-go,tspclient-goandoras-go, with the exact versions pinned ingo.modinternal/trees, pluggability)runSignandrunVerifyend-to-end flowsMakefiletargets, version injection, CI/CD pipelinePrinciples I tried to follow
These came directly out of the review discussion on #1359 — thank you @shizhMSFT for the steer:
go doc ./.../ pkg.go.dev instead, so it can't drift into being wrong.Thoughts and open questions for the team
I'd genuinely value opinions on these — happy to take it in whatever direction the maintainers prefer:
signing-schemerow and the trust store identity types.notation-goandtspclient-goare pinned to untagged commits. Useful context for newcomers, or noise that will go stale? Happy to drop it.cmd/notation/main.gochanges withoutARCHITECTURE.mdbeing touched), or is that more friction than it's worth?building.mdseemed natural, but I'm happy to move it underspecs/ordocs/if that fits the repo's conventions better.Please treat every section as negotiable — I'm very happy to cut, reshape, or rewrite based on what the team finds useful. 🙏
Signed commits ✅