notari 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- notari-0.3.0/.github/ISSUE_TEMPLATE/bug_report.md +51 -0
- notari-0.3.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
- notari-0.3.0/.github/ISSUE_TEMPLATE/feature_request.md +32 -0
- notari-0.3.0/.github/ISSUE_TEMPLATE/missed_dangerous_action.md +50 -0
- notari-0.3.0/.github/dependabot.yml +52 -0
- notari-0.3.0/.github/pull_request_template.md +37 -0
- notari-0.3.0/.github/workflows/ci.yml +66 -0
- notari-0.3.0/.github/workflows/notari-check.yml +57 -0
- notari-0.3.0/.github/workflows/release.yml +71 -0
- notari-0.3.0/.gitignore +104 -0
- notari-0.3.0/CHANGELOG.md +415 -0
- notari-0.3.0/CITATION.cff +24 -0
- notari-0.3.0/CONTRIBUTING.md +58 -0
- notari-0.3.0/LICENSE +21 -0
- notari-0.3.0/NOTICE +41 -0
- notari-0.3.0/PKG-INFO +513 -0
- notari-0.3.0/README.md +447 -0
- notari-0.3.0/SECURITY.md +85 -0
- notari-0.3.0/action.yml +174 -0
- notari-0.3.0/docs/LAUNCH-DRY-RUN-0.3.0.md +104 -0
- notari-0.3.0/docs/LEARNING-LOOP.md +97 -0
- notari-0.3.0/docs/PRODUCT.md +106 -0
- notari-0.3.0/docs/QUICKSTART.md +162 -0
- notari-0.3.0/docs/SECURITY-MODEL.md +530 -0
- notari-0.3.0/docs/assets/notari-flow-dark.svg +71 -0
- notari-0.3.0/docs/assets/notari-flow-light.svg +71 -0
- notari-0.3.0/docs/assets/notari-trust-dark.svg +61 -0
- notari-0.3.0/docs/assets/notari-trust-light.svg +61 -0
- notari-0.3.0/docs/secure-workflow.yml +53 -0
- notari-0.3.0/examples/change_control_demo.sh +113 -0
- notari-0.3.0/pyproject.toml +248 -0
- notari-0.3.0/scripts/notari-passport.sh +296 -0
- notari-0.3.0/scripts/verify_launch_readiness.py +350 -0
- notari-0.3.0/src/notari/__init__.py +50 -0
- notari-0.3.0/src/notari/__main__.py +13 -0
- notari-0.3.0/src/notari/_version.py +1 -0
- notari-0.3.0/src/notari/adapters/__init__.py +7 -0
- notari-0.3.0/src/notari/adapters/claude_code.py +1523 -0
- notari-0.3.0/src/notari/adapters/cursor.py +530 -0
- notari-0.3.0/src/notari/approvals.py +258 -0
- notari-0.3.0/src/notari/attest.py +197 -0
- notari-0.3.0/src/notari/audit.py +349 -0
- notari-0.3.0/src/notari/audit_summary.py +674 -0
- notari-0.3.0/src/notari/bridge.py +83 -0
- notari-0.3.0/src/notari/cli.py +5041 -0
- notari-0.3.0/src/notari/code_scan.py +242 -0
- notari-0.3.0/src/notari/config.py +303 -0
- notari-0.3.0/src/notari/contract.py +264 -0
- notari-0.3.0/src/notari/controls.toml +430 -0
- notari-0.3.0/src/notari/decay.py +307 -0
- notari-0.3.0/src/notari/doctor.py +531 -0
- notari-0.3.0/src/notari/errors.py +43 -0
- notari-0.3.0/src/notari/events.py +100 -0
- notari-0.3.0/src/notari/explain.py +353 -0
- notari-0.3.0/src/notari/explain_html.py +111 -0
- notari-0.3.0/src/notari/exports.py +563 -0
- notari-0.3.0/src/notari/githook.py +283 -0
- notari-0.3.0/src/notari/github_review.py +130 -0
- notari-0.3.0/src/notari/hints.py +187 -0
- notari-0.3.0/src/notari/hints.toml +99 -0
- notari-0.3.0/src/notari/insights.py +364 -0
- notari-0.3.0/src/notari/integrate.py +288 -0
- notari-0.3.0/src/notari/journal.py +435 -0
- notari-0.3.0/src/notari/learn.py +516 -0
- notari-0.3.0/src/notari/learning.py +893 -0
- notari-0.3.0/src/notari/lessons.py +360 -0
- notari-0.3.0/src/notari/onboard.py +456 -0
- notari-0.3.0/src/notari/otel.py +195 -0
- notari-0.3.0/src/notari/overnight.py +304 -0
- notari-0.3.0/src/notari/passport.py +331 -0
- notari-0.3.0/src/notari/paths.py +67 -0
- notari-0.3.0/src/notari/pause.py +215 -0
- notari-0.3.0/src/notari/perimeter.py +266 -0
- notari-0.3.0/src/notari/pinning.py +258 -0
- notari-0.3.0/src/notari/policy.py +1724 -0
- notari-0.3.0/src/notari/prompt.py +270 -0
- notari-0.3.0/src/notari/prompt_injection.py +317 -0
- notari-0.3.0/src/notari/provenance.py +237 -0
- notari-0.3.0/src/notari/py.typed +0 -0
- notari-0.3.0/src/notari/readiness.py +247 -0
- notari-0.3.0/src/notari/receipt.py +318 -0
- notari-0.3.0/src/notari/roster.py +139 -0
- notari-0.3.0/src/notari/saves.py +456 -0
- notari-0.3.0/src/notari/secrets.py +405 -0
- notari-0.3.0/src/notari/session.py +294 -0
- notari-0.3.0/src/notari/session_approvals.py +147 -0
- notari-0.3.0/src/notari/severity.py +151 -0
- notari-0.3.0/src/notari/taint.py +250 -0
- notari-0.3.0/src/notari/teach.py +164 -0
- notari-0.3.0/src/notari/telemetry.py +279 -0
- notari-0.3.0/src/notari/tool_scan.py +269 -0
- notari-0.3.0/src/notari/touchid.py +187 -0
- notari-0.3.0/src/notari/transparency.py +246 -0
- notari-0.3.0/src/notari/verify.py +1173 -0
- notari-0.3.0/tests/conftest.py +46 -0
- notari-0.3.0/tests/test_action_wrapper.py +287 -0
- notari-0.3.0/tests/test_adapter_imports.py +57 -0
- notari-0.3.0/tests/test_approvals.py +248 -0
- notari-0.3.0/tests/test_attest.py +97 -0
- notari-0.3.0/tests/test_audit.py +298 -0
- notari-0.3.0/tests/test_audit_fixes_tier0.py +142 -0
- notari-0.3.0/tests/test_audit_fixes_tier1.py +138 -0
- notari-0.3.0/tests/test_audit_fixes_tier2.py +198 -0
- notari-0.3.0/tests/test_audit_summary.py +797 -0
- notari-0.3.0/tests/test_auto_promote.py +85 -0
- notari-0.3.0/tests/test_bench_hot_path.py +192 -0
- notari-0.3.0/tests/test_block_secrets_config.py +70 -0
- notari-0.3.0/tests/test_bypass_mode.py +131 -0
- notari-0.3.0/tests/test_change_control.py +308 -0
- notari-0.3.0/tests/test_classified_by.py +53 -0
- notari-0.3.0/tests/test_classify_command.py +193 -0
- notari-0.3.0/tests/test_claude_hook.py +795 -0
- notari-0.3.0/tests/test_cli_integration.py +488 -0
- notari-0.3.0/tests/test_code_scan.py +103 -0
- notari-0.3.0/tests/test_contract_expiry.py +161 -0
- notari-0.3.0/tests/test_cursor_hook.py +236 -0
- notari-0.3.0/tests/test_decay.py +146 -0
- notari-0.3.0/tests/test_determinism.py +195 -0
- notari-0.3.0/tests/test_diff_binary_rename.py +88 -0
- notari-0.3.0/tests/test_diff_quoted_paths.py +51 -0
- notari-0.3.0/tests/test_disable_auth.py +181 -0
- notari-0.3.0/tests/test_doc_counts.py +45 -0
- notari-0.3.0/tests/test_explain.py +301 -0
- notari-0.3.0/tests/test_exports.py +228 -0
- notari-0.3.0/tests/test_false_positives_2026_06.py +128 -0
- notari-0.3.0/tests/test_gitattributes_secret.py +62 -0
- notari-0.3.0/tests/test_gitattributes_surface.py +71 -0
- notari-0.3.0/tests/test_githook.py +289 -0
- notari-0.3.0/tests/test_github_review.py +93 -0
- notari-0.3.0/tests/test_init_readiness.py +102 -0
- notari-0.3.0/tests/test_insights.py +292 -0
- notari-0.3.0/tests/test_integrate.py +264 -0
- notari-0.3.0/tests/test_journal.py +178 -0
- notari-0.3.0/tests/test_kill_test_2026_06.py +259 -0
- notari-0.3.0/tests/test_launch_smoke.py +138 -0
- notari-0.3.0/tests/test_learn.py +257 -0
- notari-0.3.0/tests/test_learning_cleanup.py +342 -0
- notari-0.3.0/tests/test_learning_cli.py +271 -0
- notari-0.3.0/tests/test_learning_concurrency.py +213 -0
- notari-0.3.0/tests/test_learning_core.py +262 -0
- notari-0.3.0/tests/test_learning_drift.py +163 -0
- notari-0.3.0/tests/test_learning_hook_integration.py +284 -0
- notari-0.3.0/tests/test_learning_overrides.py +344 -0
- notari-0.3.0/tests/test_learning_real_log_replay.py +179 -0
- notari-0.3.0/tests/test_learning_self_test.py +149 -0
- notari-0.3.0/tests/test_lessons.py +312 -0
- notari-0.3.0/tests/test_onboard.py +217 -0
- notari-0.3.0/tests/test_otel.py +164 -0
- notari-0.3.0/tests/test_overnight.py +520 -0
- notari-0.3.0/tests/test_pause.py +142 -0
- notari-0.3.0/tests/test_perimeter_casefold.py +75 -0
- notari-0.3.0/tests/test_pinning.py +140 -0
- notari-0.3.0/tests/test_policy.py +216 -0
- notari-0.3.0/tests/test_prompt_injection.py +268 -0
- notari-0.3.0/tests/test_readiness.py +82 -0
- notari-0.3.0/tests/test_receipt_narrate.py +225 -0
- notari-0.3.0/tests/test_rename_and_inventory.py +196 -0
- notari-0.3.0/tests/test_resource_limits.py +130 -0
- notari-0.3.0/tests/test_roster.py +67 -0
- notari-0.3.0/tests/test_saves.py +428 -0
- notari-0.3.0/tests/test_secrets.py +366 -0
- notari-0.3.0/tests/test_secure_workflow_isolation.py +158 -0
- notari-0.3.0/tests/test_security_gates_2026_05.py +329 -0
- notari-0.3.0/tests/test_security_regressions.py +515 -0
- notari-0.3.0/tests/test_self_disable_classifier.py +96 -0
- notari-0.3.0/tests/test_sensitive_surfaces_agent.py +144 -0
- notari-0.3.0/tests/test_session_approvals.py +94 -0
- notari-0.3.0/tests/test_severity.py +124 -0
- notari-0.3.0/tests/test_submodule_policy.py +106 -0
- notari-0.3.0/tests/test_symlink_policy.py +79 -0
- notari-0.3.0/tests/test_telemetry.py +197 -0
- notari-0.3.0/tests/test_touchid.py +234 -0
- notari-0.3.0/tests/test_transparency.py +109 -0
- notari-0.3.0/tests/test_trust_layer.py +288 -0
- notari-0.3.0/tests/test_trust_root_path.py +47 -0
- notari-0.3.0/tests/test_trust_spine.py +433 -0
- notari-0.3.0/tests/test_verify_passport_validity.py +114 -0
- notari-0.3.0/uv.lock +2044 -0
- notari-0.3.0/web/logo_1024x1024.png +0 -0
- notari-0.3.0/web/logo_400x400.png +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Something Notari should do but doesn't, or shouldn't do but does
|
|
4
|
+
title: "bug: "
|
|
5
|
+
labels: ["bug"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!--
|
|
9
|
+
Before filing: please confirm the bug reproduces on the latest released
|
|
10
|
+
version. `notari version` to check.
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
## What happened
|
|
14
|
+
|
|
15
|
+
A clear description of the bug. Include the exact command or tool call
|
|
16
|
+
that triggered it.
|
|
17
|
+
|
|
18
|
+
## What you expected
|
|
19
|
+
|
|
20
|
+
A description of what Notari should have done instead.
|
|
21
|
+
|
|
22
|
+
## Steps to reproduce
|
|
23
|
+
|
|
24
|
+
1.
|
|
25
|
+
2.
|
|
26
|
+
3.
|
|
27
|
+
|
|
28
|
+
## Environment
|
|
29
|
+
|
|
30
|
+
- OS: <!-- macOS / Linux / Windows + version -->
|
|
31
|
+
- Notari version: <!-- output of `notari version` -->
|
|
32
|
+
- Python version: <!-- output of `python --version` -->
|
|
33
|
+
- Coding agent: <!-- Claude Code / Cursor / Cline / etc. and version -->
|
|
34
|
+
|
|
35
|
+
## Relevant audit log entries
|
|
36
|
+
|
|
37
|
+
If the bug involves a gate decision, paste the relevant `~/.notari/audit.log.jsonl`
|
|
38
|
+
lines. Strip any sensitive args before pasting; Notari's redaction normally
|
|
39
|
+
keeps these out but verify.
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## `notari doctor` output
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Anything else
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security disclosure
|
|
4
|
+
url: https://github.com/manumarri-sudo/notari/security/advisories/new
|
|
5
|
+
about: Report a vulnerability privately (preferred over filing a public issue)
|
|
6
|
+
- name: Threat-model review
|
|
7
|
+
url: https://github.com/manumarri-sudo/notari/blob/main/SECURITY.md
|
|
8
|
+
about: Read SECURITY.md first if your question is about the threat model
|
|
9
|
+
- name: How to integrate with my coding agent
|
|
10
|
+
url: https://github.com/manumarri-sudo/notari/blob/main/docs/clients.md
|
|
11
|
+
about: Per-client integration recipes (Claude Code, Cursor, Cline, Aider, Continue, Windsurf, Zed)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: A capability Notari should have
|
|
4
|
+
title: "feat: "
|
|
5
|
+
labels: ["enhancement"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## The problem this solves
|
|
9
|
+
|
|
10
|
+
Describe the situation where Notari falls short today. Focus on the
|
|
11
|
+
workflow, not the implementation.
|
|
12
|
+
|
|
13
|
+
## The proposed feature
|
|
14
|
+
|
|
15
|
+
What should Notari do? Be specific about the user-facing surface (new
|
|
16
|
+
CLI command, new policy override, new event type, etc.).
|
|
17
|
+
|
|
18
|
+
## Why this matters
|
|
19
|
+
|
|
20
|
+
Who benefits? Roughly how many users / customer accounts? Any compliance
|
|
21
|
+
or insurance angle?
|
|
22
|
+
|
|
23
|
+
## Alternatives considered
|
|
24
|
+
|
|
25
|
+
What else could solve this? Why is the proposed feature better?
|
|
26
|
+
|
|
27
|
+
## Sketch
|
|
28
|
+
|
|
29
|
+
If you have a sketch of the API / TOML / event-type shape, paste it here.
|
|
30
|
+
Not required.
|
|
31
|
+
|
|
32
|
+
## Anything else
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Missed dangerous action
|
|
3
|
+
about: An agent ran a command Notari should have refused
|
|
4
|
+
title: "missed-action: "
|
|
5
|
+
labels: ["missed-dangerous-action", "policy"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!--
|
|
9
|
+
This is the highest-signal issue type for Notari. Every accepted issue
|
|
10
|
+
ships as a new pattern in src/notari/policy.py or src/notari/secrets.py
|
|
11
|
+
in the next release. Reproducibility matters more than narrative.
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
## The action Notari let through
|
|
15
|
+
|
|
16
|
+
Exact command, tool name, and args (redact secrets):
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Why this is dangerous
|
|
23
|
+
|
|
24
|
+
One or two sentences. If it's a well-known CVE class, link the CVE.
|
|
25
|
+
|
|
26
|
+
## What Notari should have done
|
|
27
|
+
|
|
28
|
+
`Risk.CRITICAL` (block + type-to-confirm) / `Risk.HIGH` (ask y/N) / other?
|
|
29
|
+
|
|
30
|
+
## Synthetic reproduction
|
|
31
|
+
|
|
32
|
+
A safe test command that exercises the same pattern Notari should match
|
|
33
|
+
against. Doesn't have to actually be destructive; the regex must catch it.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Relevant policy section
|
|
40
|
+
|
|
41
|
+
If you've already located the regex set that should have fired, link
|
|
42
|
+
the relevant constant in [`src/notari/policy.py`](../../src/notari/policy.py).
|
|
43
|
+
|
|
44
|
+
## Environment
|
|
45
|
+
|
|
46
|
+
- Notari version:
|
|
47
|
+
- Coding agent + version:
|
|
48
|
+
- OS:
|
|
49
|
+
|
|
50
|
+
## Anything else
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Dependabot keeps Notari's deps current with weekly PRs.
|
|
2
|
+
# Three ecosystems matter here: the Python runtime deps, the GitHub Actions
|
|
3
|
+
# we run on every CI / release, and the optional extras (weasyprint,
|
|
4
|
+
# pyobjc-LocalAuthentication, asyncpg, opentelemetry) shipped under
|
|
5
|
+
# `[pdf]`, `[touchid]`, `[postgres]`, and `[otel]`.
|
|
6
|
+
#
|
|
7
|
+
# Security updates ship immediately regardless of the weekly cadence.
|
|
8
|
+
|
|
9
|
+
version: 2
|
|
10
|
+
|
|
11
|
+
updates:
|
|
12
|
+
# Python deps (project + dev + optional extras).
|
|
13
|
+
- package-ecosystem: "pip"
|
|
14
|
+
directory: "/"
|
|
15
|
+
schedule:
|
|
16
|
+
interval: "weekly"
|
|
17
|
+
day: "monday"
|
|
18
|
+
time: "07:00"
|
|
19
|
+
timezone: "America/Chicago"
|
|
20
|
+
open-pull-requests-limit: 5
|
|
21
|
+
groups:
|
|
22
|
+
# Pin all dev-tooling bumps into a single PR per week so the noise
|
|
23
|
+
# stays low. ruff / mypy / pyright / pytest move together anyway.
|
|
24
|
+
dev-tooling:
|
|
25
|
+
patterns:
|
|
26
|
+
- "ruff"
|
|
27
|
+
- "mypy"
|
|
28
|
+
- "pyright"
|
|
29
|
+
- "pytest*"
|
|
30
|
+
- "hypothesis"
|
|
31
|
+
- "syrupy"
|
|
32
|
+
- "pip-audit"
|
|
33
|
+
labels:
|
|
34
|
+
- "dependencies"
|
|
35
|
+
- "python"
|
|
36
|
+
commit-message:
|
|
37
|
+
prefix: "deps"
|
|
38
|
+
include: "scope"
|
|
39
|
+
|
|
40
|
+
# GitHub Actions versions used in ci.yml and release.yml.
|
|
41
|
+
- package-ecosystem: "github-actions"
|
|
42
|
+
directory: "/"
|
|
43
|
+
schedule:
|
|
44
|
+
interval: "weekly"
|
|
45
|
+
day: "monday"
|
|
46
|
+
open-pull-requests-limit: 3
|
|
47
|
+
labels:
|
|
48
|
+
- "dependencies"
|
|
49
|
+
- "github-actions"
|
|
50
|
+
commit-message:
|
|
51
|
+
prefix: "ci"
|
|
52
|
+
include: "scope"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Thanks for opening a PR.
|
|
3
|
+
|
|
4
|
+
Before submitting, please run:
|
|
5
|
+
pytest --no-cov
|
|
6
|
+
ruff check src tests
|
|
7
|
+
ruff format --check src tests
|
|
8
|
+
|
|
9
|
+
If the change touches the gate (policy.py, classify_command, secrets.py,
|
|
10
|
+
adapters/), add a test that exercises the new behavior. The audit-log
|
|
11
|
+
chain is the deliverable; if your change can break the chain shape,
|
|
12
|
+
mention it explicitly here.
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
## What this changes
|
|
16
|
+
|
|
17
|
+
A short description of what's different after this PR. The "why" matters
|
|
18
|
+
more than the "what"; the diff shows the what.
|
|
19
|
+
|
|
20
|
+
## How it was tested
|
|
21
|
+
|
|
22
|
+
- [ ] `pytest --no-cov` passes locally
|
|
23
|
+
- [ ] `ruff check src tests` passes
|
|
24
|
+
- [ ] If you added a new tool-call risk pattern: a unit test in `test_classify_command.py` or `test_secrets.py` exercises it
|
|
25
|
+
- [ ] If you changed the audit-log event taxonomy: a test in `test_audit.py` exercises chain integrity across the new event type
|
|
26
|
+
|
|
27
|
+
## Anything reviewers should know
|
|
28
|
+
|
|
29
|
+
Edge cases, dependencies on other in-flight PRs, things you're explicitly
|
|
30
|
+
not addressing in this PR but plan to follow up on.
|
|
31
|
+
|
|
32
|
+
## Checklist
|
|
33
|
+
|
|
34
|
+
- [ ] Tests pass locally
|
|
35
|
+
- [ ] CHANGELOG.md `[Unreleased]` section updated if the change is user-facing
|
|
36
|
+
- [ ] README.md updated if the change adds a new CLI command or changes an existing one
|
|
37
|
+
- [ ] No em dashes in user-facing text
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e ".[dev]"
|
|
28
|
+
|
|
29
|
+
- name: Lint
|
|
30
|
+
run: ruff check src tests
|
|
31
|
+
|
|
32
|
+
- name: Format check
|
|
33
|
+
run: ruff format --check src tests
|
|
34
|
+
|
|
35
|
+
- name: Type-check (mypy)
|
|
36
|
+
run: mypy src/notari # blocking: strict is green and the py.typed marker promises it
|
|
37
|
+
|
|
38
|
+
- name: Test
|
|
39
|
+
run: pytest tests/ # enforces --cov-fail-under=75 from pyproject (currently ~82%)
|
|
40
|
+
|
|
41
|
+
- name: Audit dependencies
|
|
42
|
+
# Audit a frozen list that excludes the editable notari itself: its
|
|
43
|
+
# working version may not exist on PyPI yet (e.g. unreleased 0.3.0),
|
|
44
|
+
# which --strict treats as a hard error whether skipped or not.
|
|
45
|
+
# Every real dependency stays under --strict: a CVE fails the build.
|
|
46
|
+
run: |
|
|
47
|
+
pip freeze --exclude-editable > /tmp/audit-requirements.txt
|
|
48
|
+
pip-audit --strict --no-deps -r /tmp/audit-requirements.txt
|
|
49
|
+
|
|
50
|
+
build:
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
needs: test
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
55
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
|
56
|
+
with:
|
|
57
|
+
python-version: "3.12"
|
|
58
|
+
- name: Build sdist + wheel
|
|
59
|
+
run: |
|
|
60
|
+
pip install build
|
|
61
|
+
python -m build
|
|
62
|
+
- name: Upload artifacts
|
|
63
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
64
|
+
with:
|
|
65
|
+
name: dist
|
|
66
|
+
path: dist/
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: notari-change-control
|
|
2
|
+
|
|
3
|
+
# Gate every pull request: verify the diff against the human-approved contract
|
|
4
|
+
# (.notari/contract.json) and publish a Change Passport as a Status Check.
|
|
5
|
+
#
|
|
6
|
+
# ⚠ DOGFOOD CONFIGURATION: This workflow uses `uses: ./` and `install-from-source`
|
|
7
|
+
# because this repo IS the Notari source — we verify with HEAD's own code. A
|
|
8
|
+
# CONSUMER of Notari should NEVER do this; pin the release commit SHA instead
|
|
9
|
+
# (docs/secure-workflow.yml carries the current pin):
|
|
10
|
+
#
|
|
11
|
+
# uses: manumarri-sudo/notari@<full-release-commit-sha> # vX.Y.Z
|
|
12
|
+
#
|
|
13
|
+
# See README.md and docs/SECURITY-MODEL.md for the secure deployment checklist.
|
|
14
|
+
on:
|
|
15
|
+
pull_request:
|
|
16
|
+
branches: [main]
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
statuses: write # publish the commit Status Check
|
|
21
|
+
pull-requests: write # (reserved) post the passport as a PR comment
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
change-control:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout (full history so the base commit is available)
|
|
28
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
29
|
+
with:
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
|
|
32
|
+
# No skip-on-missing-contract: the Action itself fails closed (exit 2)
|
|
33
|
+
# when no contract exists. Skipping was a fail-open: GitHub reports
|
|
34
|
+
# skipped jobs as successful, so a PR that deletes the contract would
|
|
35
|
+
# pass the required check.
|
|
36
|
+
- name: Notari Change Control
|
|
37
|
+
id: notari
|
|
38
|
+
# install-from-source: ONLY safe for the repo that owns the Action.
|
|
39
|
+
# Consumers pin a published tag so a PR cannot modify the gate.
|
|
40
|
+
uses: ./
|
|
41
|
+
with:
|
|
42
|
+
install-from-source: "true"
|
|
43
|
+
head: ${{ github.event.pull_request.head.sha }}
|
|
44
|
+
head-sha: ${{ github.event.pull_request.head.sha }}
|
|
45
|
+
fail-on-block: "true"
|
|
46
|
+
strict: "true"
|
|
47
|
+
gate-key: ${{ secrets.NOTARI_GATE_KEY }}
|
|
48
|
+
gate-pubkeys: ${{ vars.NOTARI_GATE_PUBKEYS }}
|
|
49
|
+
approver-pubkeys: ${{ secrets.NOTARI_APPROVER_PUBKEYS }}
|
|
50
|
+
# Dogfood without a gate key: accept report-grade unsigned evidence.
|
|
51
|
+
allow-unsigned-evidence: "true"
|
|
52
|
+
# Dogfood: this repo uses pull_request + install-from-source because it
|
|
53
|
+
# IS the Notari source. Consumers MUST use pull_request_target instead.
|
|
54
|
+
allow-pull-request-trigger: "true"
|
|
55
|
+
|
|
56
|
+
- name: Report verdict
|
|
57
|
+
run: echo "Notari verdict was ${{ steps.notari.outputs.verdict }}"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Auto-publishes to PyPI when a GitHub release is published. Uses PyPI
|
|
4
|
+
# Trusted Publishing (OIDC) so no API token lives in repo secrets. One-time
|
|
5
|
+
# setup required on the PyPI side: register manumarri-sudo/notari as a
|
|
6
|
+
# trusted publisher for the `notari` project with workflow `release.yml`
|
|
7
|
+
# and environment `pypi`. The PyPI dist is `notari` because `notari` was
|
|
8
|
+
# taken; the package, CLI binary, and config dir all remain `notari`. See:
|
|
9
|
+
# https://docs.pypi.org/trusted-publishers/
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
release:
|
|
13
|
+
types: [published]
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build-and-publish:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
environment:
|
|
19
|
+
name: pypi
|
|
20
|
+
url: https://pypi.org/p/notari
|
|
21
|
+
permissions:
|
|
22
|
+
# Required for Trusted Publishing OIDC token exchange.
|
|
23
|
+
id-token: write
|
|
24
|
+
# Required to attach SBOM / attestations to the release.
|
|
25
|
+
contents: write
|
|
26
|
+
attestations: write
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
|
|
33
|
+
- name: Set up Python
|
|
34
|
+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.12"
|
|
37
|
+
|
|
38
|
+
- name: Install build deps
|
|
39
|
+
run: |
|
|
40
|
+
python -m pip install --upgrade pip build twine
|
|
41
|
+
|
|
42
|
+
- name: Verify tag matches pyproject version
|
|
43
|
+
run: |
|
|
44
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
45
|
+
pkg=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
46
|
+
if [ "$tag" != "$pkg" ]; then
|
|
47
|
+
echo "::error::tag $tag != pyproject version $pkg"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
echo "tag and pyproject agree on version: $pkg"
|
|
51
|
+
|
|
52
|
+
- name: Build sdist + wheel
|
|
53
|
+
run: python -m build
|
|
54
|
+
|
|
55
|
+
- name: Twine check
|
|
56
|
+
run: twine check dist/*
|
|
57
|
+
|
|
58
|
+
- name: Publish to PyPI via Trusted Publishing
|
|
59
|
+
# Tolerated until PyPI Trusted Publishing is registered for `notari`.
|
|
60
|
+
# Without TP the OIDC handshake fails; once TP is in place this step
|
|
61
|
+
# publishes cleanly and `skip-existing: true` keeps re-runs idempotent.
|
|
62
|
+
continue-on-error: true
|
|
63
|
+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
|
|
64
|
+
with:
|
|
65
|
+
packages-dir: dist/
|
|
66
|
+
skip-existing: true
|
|
67
|
+
|
|
68
|
+
- name: Generate attestations
|
|
69
|
+
uses: actions/attest-build-provenance@ef244123eb79f2f7a7e75d99086184180e6d0018 # v1
|
|
70
|
+
with:
|
|
71
|
+
subject-path: "dist/*"
|
notari-0.3.0/.gitignore
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# --- Python ---
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
*.egg
|
|
8
|
+
*.egg-info/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
wheels/
|
|
12
|
+
.eggs/
|
|
13
|
+
MANIFEST
|
|
14
|
+
|
|
15
|
+
# --- Virtualenvs ---
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
ENV/
|
|
20
|
+
|
|
21
|
+
# --- Tooling caches ---
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.ruff_cache/
|
|
24
|
+
.mypy_cache/
|
|
25
|
+
.pyright/
|
|
26
|
+
.tox/
|
|
27
|
+
.cache/
|
|
28
|
+
pytest-cache-files-*/
|
|
29
|
+
|
|
30
|
+
# --- Coverage ---
|
|
31
|
+
.coverage
|
|
32
|
+
.coverage.*
|
|
33
|
+
htmlcov/
|
|
34
|
+
coverage.xml
|
|
35
|
+
*.cover
|
|
36
|
+
|
|
37
|
+
# --- IDE / editor ---
|
|
38
|
+
.vscode/
|
|
39
|
+
.idea/
|
|
40
|
+
*.swp
|
|
41
|
+
*.swo
|
|
42
|
+
.DS_Store
|
|
43
|
+
|
|
44
|
+
# --- Notari runtime artifacts (NEVER commit) ---
|
|
45
|
+
# The signing key is per-installation and must never be checked in.
|
|
46
|
+
.notari/
|
|
47
|
+
~/.notari/
|
|
48
|
+
|
|
49
|
+
# Audit logs are user data with timestamps; keep out of source control.
|
|
50
|
+
*.audit.log.jsonl
|
|
51
|
+
audit.log.jsonl
|
|
52
|
+
|
|
53
|
+
# Claude Code session logs - may contain transcripts / tokens; never commit.
|
|
54
|
+
.claude-logs/
|
|
55
|
+
|
|
56
|
+
# --- Local secrets ---
|
|
57
|
+
.env
|
|
58
|
+
.env.local
|
|
59
|
+
.env.*.local
|
|
60
|
+
*.key
|
|
61
|
+
*.pem
|
|
62
|
+
secrets.json
|
|
63
|
+
|
|
64
|
+
# --- Generated experiment artifacts ---
|
|
65
|
+
# The harness scripts are committed; the generated runs are not.
|
|
66
|
+
experiments/results/
|
|
67
|
+
experiments/results.zip
|
|
68
|
+
|
|
69
|
+
# --- OS ---
|
|
70
|
+
Thumbs.db
|
|
71
|
+
.DS_Store
|
|
72
|
+
|
|
73
|
+
# Local-only PDF renders of markdown launch material
|
|
74
|
+
web/pdfs/
|
|
75
|
+
|
|
76
|
+
# Internal strategy / research / critique drafts and their binary renders.
|
|
77
|
+
# Keep local; the public threat model lives at docs/SECURITY-MODEL.md.
|
|
78
|
+
docs/research/
|
|
79
|
+
|
|
80
|
+
# Internal launch / go-to-market / business material. Kept local, not public.
|
|
81
|
+
LAUNCH.md
|
|
82
|
+
docs/distribution.md
|
|
83
|
+
docs/marketing/messaging-guide.md
|
|
84
|
+
docs/marketing/coding-agent-incident-recovery.md
|
|
85
|
+
docs/marketing/engagement-terms-template.md
|
|
86
|
+
docs/marketing/substack-draft-disaster-to-deadline.md
|
|
87
|
+
docs/marketing/future-loomiq-saas/
|
|
88
|
+
docs/marketing/outreach/
|
|
89
|
+
|
|
90
|
+
# Internal experiment harness and backend infra (telemetry/analysis).
|
|
91
|
+
# The client-side telemetry code stays public at src/notari/telemetry.py.
|
|
92
|
+
experiments/
|
|
93
|
+
infra/
|
|
94
|
+
|
|
95
|
+
# marketing drafts: pre-pivot product positioning + compliance claims; kept
|
|
96
|
+
# local until a Change-Control-aligned rewrite (see FINISH-STATUS.md). Not shipped.
|
|
97
|
+
docs/marketing/
|
|
98
|
+
|
|
99
|
+
# Manus private research cache (screenshots + competitor notes); not shipped
|
|
100
|
+
research-screenshots/
|
|
101
|
+
|
|
102
|
+
# internal worklists (security findings + triage); kept local, not public
|
|
103
|
+
AUDIT-FIX-PLAN.md
|
|
104
|
+
FINISH-STATUS.md
|