feat(csl): Community Specification License 1.0 compliance plugin - #449
Conversation
mlieberman85
left a comment
There was a problem hiding this comment.
This looks correct. The handler design is right in the way that matters most here: a missing file returns a dispositive FAIL, a present file defers to the LLM as suggestive, so the control cannot manufacture a PASS. test_placeholder_fails asserting that a template placeholder does not count as a filled-in file is the same trap #445 and #431 fall into.
Three things to fix, two of them one-liners:
get_framework_config_path()should useimportlib.resources-- CLAUDE.md:145 states it as a MUST and the three shipped plugins all do it. Suggestions inline on the three call sites.- The
fixtures/directory at the repo root does not appear to be read by anything. - The
server/registry.pychange is untested.
On the registry change itself: the approach is right and the _bind_tool_config reference checks out -- factory.py:21-51 does the same wrap-inject-strip. Since that logic now exists in two places, docs/design/builtin-tool-factories.md:72 already proposes extracting it; worth linking from there rather than doing it in this PR.
|
|
||
| def get_framework_config_path(self) -> Path | None: | ||
| """Absolute path to the bundled TOML config (the source of truth).""" | ||
| return Path(__file__).parent / "community-spec.toml" |
There was a problem hiding this comment.
CLAUDE.md:145 requires importlib.resources here. The __file__ form works for a normal wheel but breaks under zipimport and frozen installs, which is what feature 021 fixed.
darnit-gittuf also raises FileNotFoundError with a build-problem message when the TOML is missing -- worth copying if you want the same diagnostic.
| return Path(__file__).parent / "community-spec.toml" | |
| from importlib.resources import files | |
| return Path(str(files(__package__) / "community-spec.toml")) |
There was a problem hiding this comment.
Done. Went with the full gittuf form including the FileNotFoundError diagnostic, so the failure mode matches darnit-gittuf rather than just the resolution
| [project.entry-points."darnit.frameworks"] | ||
| community-spec = "darnit_csl:get_framework_path" | ||
| """ | ||
| return Path(__file__).parent / "community-spec.toml" |
There was a problem hiding this comment.
darnit-gittuf has the same two entry points and delegates rather than reimplementing, so both resolve the TOML the same way:
| return Path(__file__).parent / "community-spec.toml" | |
| return CommunitySpecImplementation().get_framework_config_path() |
| [project.entry-points."darnit.frameworks"] | ||
| community-spec-optional = "darnit_csl:get_optional_framework_path" | ||
| """ | ||
| return Path(__file__).parent / "community-spec-optional.toml" |
There was a problem hiding this comment.
Same for the optional framework. There is no implementation method for this one, so it needs the direct form:
| return Path(__file__).parent / "community-spec-optional.toml" | |
| from importlib.resources import files | |
| return Path(str(files(__package__) / "community-spec-optional.toml")) |
There was a problem hiding this comment.
Done with the direct importlib.resources form, plus the same FileNotFoundError diagnostic for symmetry
| @@ -0,0 +1,8 @@ | |||
| # Foo Spec | |||
There was a problem hiding this comment.
These ten files land in a new top-level fixtures/ directory, and grepping the diff nothing references them -- the tests build their repos with tmp_path.
If they are demo material for docs/CSL_ONBOARDING.md, worth referencing them from it. Otherwise they look like working files that got committed.
There was a problem hiding this comment.
Working files, deleted.
| import inspect | ||
|
|
||
| sig = inspect.signature(base_fn) | ||
| bound_handler.__signature__ = sig.replace( |
There was a problem hiding this comment.
This changes how every plugin's MCP tools get exposed and there is no test for it. The test added in this PR (test_non_ascii_template_read_as_utf8) covers template encoding, not the signature stripping.
A test asserting _framework_name is absent from the exposed signature would pin it.
There was a problem hiding this comment.
Added TestBuiltinSignatureStripping in tests/darnit/server/test_registry.py, two tests: _framework_name absent from the exposed signature (and no leading-underscore params at all), and every other parameter preserved in order.
Verified they pin it: checked out main's registry.py over mine.
1679dd5 to
52e1a9d
Compare
…iation): UTF-8 templates Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
…river - remediate_community_spec MCP tool: writes the CSL 1.0 file set from a drafted scope and re-audits; rejects placeholder and mailing-list CoC contacts so generated notices never carry fake names - csl_llm_if_present sieve handler: LLM content checks run first under darnit serve; darnit audit falls back to the deterministic regex and existence passes (stop_on_llm=False in the driver/tests) - coc_contact_filled regex rejects common placeholder values - scripts/csl_onboard.py: clone -> branch -> audit -> remediate from a scope file -> placeholder scan -> print PR commands - server registry: strip _framework_name from builtin tool signatures so newer FastMCP accepts them Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
- coc_contact_filled and _PLACEHOLDER_RE also reject the bracketed "[Ideally list two different individuals ...]" boilerplate - csl_llm_if_present CSL-03.01 prompt updated to match - 3 regression tests (33 -> 36): leftover guidance fails the audit, notices render drops the guidance, CLA render uses upstream's real filenames - csl_onboard: import-order lint fix Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
- coc_policy='org': notices point at the project's existing org-level Code of Conduct (repo CoC file, org community repo, or foundation CoC such as CNCF / LF / JDF) and name no individual contacts - remediate_community_spec refuses individual contacts when the repo already has a Code of Conduct file, and requires a linked coc_reference in org mode - CSL-03.01 prompt and contacts requirement updated to accept an org-level reference; csl_onboard gains --coc-policy / --coc-reference - 4 regression tests (36 -> 40) Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
…ature stripping thanks for the review, here the implementation: - get_framework_config_path and both framework entry points now resolve via importlib.resources, with gittuf's broken-build diagnostic - get_framework_path delegates to the implementation - drop unreferenced top-level fixtures/ - test that _framework_name is stripped from the exposed builtin signature (fails 2/18 against main's registry.py, passes with the fix) Signed-off-by: Marco De Vincenzi <md6796@nyu.edu>
Adds
darnit-csl(frameworkcommunity-spec): audits specification repos for the Community Specification License 1.0 file set (CLA, license, scope, notices, licenses, governance, plus README discoverability of scope/notices) and remediates via templates or the MCPremediate_community_spectool. Code of Conduct is org-first (links the project/foundation CoC instead of naming individuals). Includesscripts/csl_onboard.pyand an onboarding guide.Already exercised on secure-systems-lab/dsse#79, in-toto/specification#98, theupdateframework/specification#317, uptane/uptane-standard#271.
40 tests in
tests/darnit_csl; ruff clean;validate_sync.pypasses. Rebased on current main, includingdefault_authorityfor the plugin's sieve handler (RFC-0001).