feat(detection-core): recognition target table and first express fact pack (8.2 part 1)

This commit is contained in:
Marius Ciepluch
2026-10-30 18:46:19 +01:00
parent 4a1167dfdd
commit 1d5a509424
5 changed files with 237 additions and 1 deletions
@@ -0,0 +1,26 @@
# Recognition-coverage target table (valid-detection-benchmark task 7.1, detection-core 8.2)
Manifest-only read of the 12 pilot-pool repositories (package.json / pyproject.toml /
setup.py at repo root); no pool labels read.
| repository | manifest | detected framework deps | in entry vocabulary |
|---|---|---|---|
| bytebase/dbhub | package.json | express | no |
| contentful/contentful-mcp-server | package.json | (workspace-local) | no |
| fastapi-users/fastapi-users | pyproject.toml | fastapi | no |
| i18next/i18next-http-middleware | package.json | express, koa | no |
| imzbf/md-editor-v3 | package.json | - | no |
| jupyter-lsp/jupyterlab-lsp | package.json | - | no |
| matrix-org/matrix-appservice-bridge | package.json | express | no |
| nvbn/thefuck | setup.py | - | no |
| ondata/ckan-mcp-server | package.json | express, @modelcontextprotocol/sdk | no |
| webpack/webpack-bundle-analyzer | package.json | - | no |
| zenitram/malla | pyproject.toml | flask | no |
| zereight/gitlab-mcp | package.json | express, @modelcontextprotocol/sdk | no |
Entry vocabulary today (`mapping/legacy.py` entry_framework): stapler, jetty, servlet,
jaxrs, symfony, livewire, laravel, remix, tornado. **0/12 pilot repos covered.**
First fact-pack target: **express** (5 repos; covers 2 of the 3 in-family access_control
pilot cases: dbhub, matrix). Script: /tmp/opencode/recognition_table_71.py; raw:
table.json.
@@ -0,0 +1,105 @@
{
"entry_vocabulary": [
"jaxrs",
"jetty",
"laravel",
"livewire",
"remix",
"servlet",
"stapler",
"symfony",
"tornado"
],
"note": "manifest-only read; no pool labels",
"repositories": [
{
"frameworks": [
"Express:express"
],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "bytebase/dbhub"
},
{
"frameworks": [],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "contentful/contentful-mcp-server"
},
{
"frameworks": [
"FastAPI:fastapi"
],
"in_entry_vocabulary": [],
"manifest": "pyproject.toml",
"repository": "fastapi-users/fastapi-users"
},
{
"frameworks": [
"Express:express",
"Koa:koa"
],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "i18next/i18next-http-middleware"
},
{
"frameworks": [],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "imzbf/md-editor-v3"
},
{
"frameworks": [],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "jupyter-lsp/jupyterlab-lsp"
},
{
"frameworks": [
"Express:express"
],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "matrix-org/matrix-appservice-bridge"
},
{
"frameworks": [],
"in_entry_vocabulary": [],
"manifest": "setup.py",
"repository": "nvbn/thefuck"
},
{
"frameworks": [
"Express:express",
"MCP:@modelcontextprotocol/sdk"
],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "ondata/ckan-mcp-server"
},
{
"frameworks": [],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "webpack/webpack-bundle-analyzer"
},
{
"frameworks": [
"Flask:flask"
],
"in_entry_vocabulary": [],
"manifest": "pyproject.toml",
"repository": "zenitram/malla"
},
{
"frameworks": [
"Express:express",
"MCP:@modelcontextprotocol/sdk"
],
"in_entry_vocabulary": [],
"manifest": "package.json",
"repository": "zereight/gitlab-mcp"
}
]
}
+21 -1
View File
@@ -11,6 +11,7 @@ import hashlib
import json import json
from collections.abc import Mapping, Sequence from collections.abc import Mapping, Sequence
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path
from typing import Any from typing import Any
@@ -52,4 +53,23 @@ def verify_fact_pack(pack: FactPack, facts: Sequence[Mapping[str, Any]]) -> None
raise FactPackError(f"fact content does not match the stamped digest of pack {pack.family!r}") raise FactPackError(f"fact content does not match the stamped digest of pack {pack.family!r}")
__all__ = ["FactPack", "FactPackError", "admit_fact_pack", "verify_fact_pack"] def admit_pack_file(path: str | Path, *, review_digest: str) -> FactPack:
"""Admit a fact-pack file only when its embedded review attestation verifies.
The pack file must carry ``review.note`` and ``review.digest`` where the digest is
the sha256 of the note; anything else is an unreviewed pack and is refused.
"""
payload = json.loads(Path(path).read_text(encoding="utf-8"))
review = payload.get("review", {})
note = review.get("note", "")
if not note or review.get("digest") != hashlib.sha256(note.encode()).hexdigest():
raise FactPackError(f"pack {path} lacks a verifiable review attestation")
if review_digest != review["digest"]:
raise FactPackError(f"pack {path}: supplied review digest does not match the embedded attestation")
facts = payload.get("facts")
if not isinstance(facts, list) or not all(isinstance(fact, dict) for fact in facts):
raise FactPackError(f"pack {path}: facts must be a list of objects")
return admit_fact_pack(str(payload.get("family", "")), facts, review_digest=review["digest"])
__all__ = ["FactPack", "FactPackError", "admit_fact_pack", "admit_pack_file", "verify_fact_pack"]
@@ -0,0 +1,33 @@
{
"facts": [
{
"defines_handler": true,
"handler_kind": "route",
"id": "entry:express:app-route",
"pattern": "app.(get|post|put|delete|patch|all|use)\\s*\\("
},
{
"defines_handler": true,
"handler_kind": "route",
"id": "entry:express:router-route",
"pattern": "router.(get|post|put|delete|patch|all|use)\\s*\\("
},
{
"defines_handler": false,
"handler_kind": "app",
"id": "entry:express:express-app",
"pattern": "express\\s*\\(\\s*\\)"
}
],
"family": "access_control",
"framework": "express",
"kind": "entry_facts",
"languages": [
"javascript",
"typescript"
],
"review": {
"digest": "47866e5c15b286d7107b101bd396f78bbbda23788085676c590c3af937085e00",
"note": "Reviewed against Express 4/5 routing docs and the pilot pool's manifest-level framework usage (2026-10-30 recognition table). Entry patterns only; no sinks, no labels."
}
}
+52
View File
@@ -0,0 +1,52 @@
"""Fact-pack file admission tests for detection-core task 8.2 (Req 10.1)."""
import hashlib
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from openultrasast.core.factpack import FactPackError, admit_pack_file, verify_fact_pack # noqa: E402
REPO = Path(__file__).resolve().parents[1]
PACK = REPO / "src/openultrasast/ruleset/entries/express.json"
def _review_digest() -> str:
payload = json.loads(PACK.read_text(encoding="utf-8"))
return hashlib.sha256(payload["review"]["note"].encode()).hexdigest()
def test_express_pack_admitted_with_verifiable_review() -> None:
pack = admit_pack_file(PACK, review_digest=_review_digest())
assert pack.family == "access_control"
assert len(pack.facts) == 3
assert pack.review_digest == _review_digest()
verify_fact_pack(pack, pack.facts)
def test_pack_refused_without_matching_review() -> None:
try:
admit_pack_file(PACK, review_digest="0" * 64)
raise AssertionError("wrong review digest must be refused")
except FactPackError:
pass
def test_tampered_pack_file_refused() -> None:
payload = json.loads(PACK.read_text(encoding="utf-8"))
payload["facts"].append({"id": "entry:express:evil", "pattern": "eval("})
tampered = PACK.parent / "tampered.json"
tampered.write_text(json.dumps(payload), encoding="utf-8")
try:
pack = admit_pack_file(tampered, review_digest=_review_digest())
# review attestation still verifies, but content no longer matches the stamped digest
original = admit_pack_file(PACK, review_digest=_review_digest())
try:
verify_fact_pack(original, pack.facts)
raise AssertionError("tampered content must fail verification")
except FactPackError:
pass
finally:
tampered.unlink()