stigmem-plugin-source-attestation 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,12 @@
1
+ """Experimental source-attestation plugin scaffold."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .config import SourceAttestationConfig
6
+ from .manifest import PLUGIN_NAME, plugin_manifest
7
+
8
+ __all__ = [
9
+ "PLUGIN_NAME",
10
+ "SourceAttestationConfig",
11
+ "plugin_manifest",
12
+ ]
@@ -0,0 +1,48 @@
1
+ """Configuration schema for the source-attestation plugin."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from collections.abc import Mapping
7
+
8
+ from pydantic import BaseModel, model_validator
9
+
10
+
11
+ class SourceAttestationConfig(BaseModel):
12
+ """Operator-controlled gates for experimental source attestation."""
13
+
14
+ enabled: bool = False
15
+ enforce_assert_validation: bool = False
16
+ apply_recall_rank: bool = False
17
+ enforce_federation_inbound: bool = False
18
+ warn_only: bool = True
19
+
20
+ @model_validator(mode="after")
21
+ def _validate_warn_only_boundary(self) -> SourceAttestationConfig:
22
+ enforcing = self.enforce_assert_validation or self.enforce_federation_inbound
23
+ if enforcing and self.warn_only:
24
+ raise ValueError("warn_only must be false when enforcement gates are enabled")
25
+ return self
26
+
27
+
28
+ def load_config_from_env(
29
+ environ: Mapping[str, str] | None = None,
30
+ ) -> SourceAttestationConfig:
31
+ """Load source-attestation plugin gates from environment variables."""
32
+
33
+ env = environ if environ is not None else os.environ
34
+ prefix = "STIGMEM_SOURCE_ATTESTATION_"
35
+ return SourceAttestationConfig(
36
+ enabled=_env_bool(env, f"{prefix}ENABLED"),
37
+ enforce_assert_validation=_env_bool(env, f"{prefix}ENFORCE_ASSERT_VALIDATION"),
38
+ apply_recall_rank=_env_bool(env, f"{prefix}APPLY_RECALL_RANK"),
39
+ enforce_federation_inbound=_env_bool(env, f"{prefix}ENFORCE_FEDERATION_INBOUND"),
40
+ warn_only=_env_bool(env, f"{prefix}WARN_ONLY", default=True),
41
+ )
42
+
43
+
44
+ def _env_bool(env: Mapping[str, str], name: str, *, default: bool = False) -> bool:
45
+ raw = env.get(name)
46
+ if raw is None:
47
+ return default
48
+ return raw.strip().lower() in {"1", "true", "yes", "on"}
@@ -0,0 +1,147 @@
1
+ """Hook handlers for the source-attestation plugin."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from pydantic import ValidationError
8
+ from stigmem_node.entity_normalizer import NormalizationError, normalize_entity_uri
9
+ from stigmem_node.plugins import Allow, Deny, PluginContext, PluginHealth, PluginHealthStatus
10
+
11
+ from .config import load_config_from_env
12
+
13
+
14
+ def config_validate(_ctx: PluginContext, **_: Any) -> Allow | Deny:
15
+ """Validate operator gates before the plugin is registered."""
16
+
17
+ try:
18
+ load_config_from_env()
19
+ except ValidationError as exc:
20
+ return Deny(f"invalid source-attestation plugin config: {exc}")
21
+ return Allow()
22
+
23
+
24
+ def pre_assert_validate(_ctx: PluginContext, **kwargs: Any) -> Allow | Deny:
25
+ """Gate source/identity binding behind explicit plugin configuration.
26
+
27
+ Returns Allow() when the plugin is disabled or assertion enforcement is not
28
+ enabled. When both gates are enabled, the handler rejects declared source
29
+ values that do not match the authenticated principal or its delegated
30
+ source-entity list.
31
+ """
32
+
33
+ config = load_config_from_env()
34
+ if not (config.enabled and config.enforce_assert_validation):
35
+ return Allow()
36
+
37
+ req = kwargs.get("req")
38
+ identity = kwargs.get("identity")
39
+ source = _normalized_or_none(getattr(req, "source", None))
40
+ authorized_sources = _authorized_source_entities(identity)
41
+ if source is not None and source in authorized_sources:
42
+ return Allow()
43
+
44
+ return Deny(
45
+ "source_attestation_failed: declared source does not match authenticated principal"
46
+ )
47
+
48
+
49
+ def recall_rank(_ctx: PluginContext, scored_results: list[Any], **kwargs: Any) -> dict[str, float]:
50
+ """Contribute source-trust score deltas only when explicitly enabled.
51
+
52
+ Returns an empty delta map when the plugin is disabled, recall ranking is
53
+ not enabled, or the active recall weights set source_trust to zero. Only
54
+ enabled deployments add source-trust contribution to caller-owned scoring.
55
+ """
56
+
57
+ config = load_config_from_env()
58
+ if not (config.enabled and config.apply_recall_rank):
59
+ return {}
60
+
61
+ from stigmem_node.source_trust import compute_source_trust
62
+
63
+ identity = kwargs.get("identity")
64
+ weights = kwargs.get("weights")
65
+ source_weight = float(getattr(weights, "source_trust", 0.0))
66
+ if source_weight <= 0.0:
67
+ return {}
68
+
69
+ base_weight = (
70
+ float(getattr(weights, "lexical", 0.0))
71
+ + float(getattr(weights, "semantic", 0.0))
72
+ + float(getattr(weights, "graph", 0.0))
73
+ + source_weight
74
+ + float(getattr(weights, "recency", 0.0))
75
+ )
76
+ if base_weight <= 0.0:
77
+ base_weight = 1.0
78
+
79
+ deltas: dict[str, float] = {}
80
+ for scored in scored_results:
81
+ fact = getattr(scored, "fact", None)
82
+ fact_id = getattr(fact, "id", None)
83
+ source = getattr(fact, "source", None)
84
+ scope = getattr(fact, "scope", None)
85
+ confidence = float(getattr(fact, "confidence", 0.0))
86
+ if fact_id is None or source is None or scope is None:
87
+ continue
88
+ trust = compute_source_trust(source, scope, identity)
89
+ deltas[str(fact_id)] = (source_weight * trust / base_weight) * max(0.0, confidence)
90
+
91
+ return deltas
92
+
93
+
94
+ def federation_inbound_validate(_ctx: PluginContext, **kwargs: Any) -> Allow | Deny:
95
+ """Gate inbound source-attestation policy behind explicit plugin configuration.
96
+
97
+ Returns Allow() when the plugin is disabled or federation-inbound
98
+ enforcement is not enabled. When both gates are enabled, the handler
99
+ rejects federated facts whose normalized source does not match the peer
100
+ node identifier or capability-token subject.
101
+ """
102
+
103
+ config = load_config_from_env()
104
+ if not (config.enabled and config.enforce_federation_inbound):
105
+ return Allow()
106
+
107
+ fact = kwargs.get("fact") or {}
108
+ fact_source = _normalized_or_none(fact.get("source")) if isinstance(fact, dict) else None
109
+ peer = kwargs.get("peer") or {}
110
+ cap_token = kwargs.get("cap_token") or {}
111
+ expected_source = None
112
+ if isinstance(peer, dict):
113
+ expected_source = peer.get("node_id")
114
+ if expected_source is None and isinstance(cap_token, dict):
115
+ expected_source = cap_token.get("subject")
116
+ if fact_source is not None and fact_source == _normalized_or_none(expected_source):
117
+ return Allow()
118
+
119
+ return Deny("source_attestation_failed: federated fact source does not match sender")
120
+
121
+
122
+ def health_check(_ctx: PluginContext) -> PluginHealth:
123
+ """Report scaffold health for registry lifecycle tests."""
124
+
125
+ return PluginHealth(
126
+ status=PluginHealthStatus.HEALTHY,
127
+ message="source attestation plugin scaffold registered",
128
+ )
129
+
130
+
131
+ def _authorized_source_entities(identity: Any) -> set[str]:
132
+ source_entities = {getattr(identity, "entity_uri", None)}
133
+ source_entities.update(getattr(identity, "allowed_source_entities", ()) or ())
134
+ return {
135
+ normalized
136
+ for raw in source_entities
137
+ if (normalized := _normalized_or_none(raw)) is not None
138
+ }
139
+
140
+
141
+ def _normalized_or_none(raw: Any) -> str | None:
142
+ if not isinstance(raw, str):
143
+ return None
144
+ try:
145
+ return normalize_entity_uri(raw)
146
+ except NormalizationError:
147
+ return None
@@ -0,0 +1,43 @@
1
+ """Plugin manifest factory for source attestation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from stigmem_node.plugins import PluginManifest
6
+
7
+ from . import handlers
8
+ from .config import SourceAttestationConfig
9
+
10
+ PLUGIN_NAME = "stigmem-plugin-source-attestation"
11
+ PLUGIN_VERSION = "0.1.0"
12
+ REQUIRES_STIGMEM = ">=0.9.0a3"
13
+
14
+
15
+ def plugin_manifest() -> PluginManifest:
16
+ """Return the entry-point manifest consumed by ``stigmem.plugins`` discovery."""
17
+
18
+ return PluginManifest(
19
+ name=PLUGIN_NAME,
20
+ version=PLUGIN_VERSION,
21
+ requires_stigmem=REQUIRES_STIGMEM,
22
+ capabilities=frozenset(
23
+ {
24
+ "facts.read",
25
+ "facts.write",
26
+ "recall.read",
27
+ "federation.read",
28
+ "federation.write",
29
+ "identity.read",
30
+ "audit.emit",
31
+ "config.read",
32
+ }
33
+ ),
34
+ hooks={
35
+ "config_validate": handlers.config_validate,
36
+ "pre_assert_validate": handlers.pre_assert_validate,
37
+ "recall_rank": handlers.recall_rank,
38
+ "federation_inbound_validate": handlers.federation_inbound_validate,
39
+ },
40
+ config_schema=SourceAttestationConfig,
41
+ health_check=handlers.health_check,
42
+ async_safe=True,
43
+ )
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: stigmem-plugin-source-attestation
3
+ Version: 0.1.0
4
+ Summary: Experimental source-attestation plugin for Stigmem.
5
+ Project-URL: Homepage, https://github.com/eidetic-labs/stigmem
6
+ Project-URL: Documentation, https://github.com/eidetic-labs/stigmem/tree/main/features/source-attestation
7
+ Project-URL: Repository, https://github.com/eidetic-labs/stigmem
8
+ Project-URL: Issues, https://github.com/eidetic-labs/stigmem/issues
9
+ Author-email: Eidetic Labs <oss@eidetic-labs.ai>
10
+ License: Apache-2.0
11
+ Keywords: federation,plugins,provenance,source-attestation,stigmem
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: pydantic<3,>=2
21
+ Requires-Dist: stigmem-node<1.0.0,>=0.9.0a8
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Stigmem Source Attestation Plugin
25
+
26
+ Experimental source attestation plugin for Stigmem.
27
+
28
+ This package provides the `stigmem-plugin-source-attestation` source package
29
+ for alpha validation. It registers through the `stigmem.plugins` entry point
30
+ group and is loaded by `stigmem-node` only when explicitly installed and
31
+ configured by an operator.
32
+
33
+ ## Status
34
+
35
+ Source attestation remains experimental. Installing this package does not add
36
+ assertion-source enforcement, recall source weighting, or federation source
37
+ guards to the supported default surface. Default installs remain inert unless
38
+ the plugin is registered and the operator enables the relevant gates.
39
+
40
+ The package metadata is publication-shaped for the plugin readiness track, but
41
+ registry publication remains on hold until dry-run evidence and maintainer
42
+ clearance are recorded. See the feature record under
43
+ `features/source-attestation/` for the current status, evidence, and security
44
+ notes.
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ pip install --pre stigmem-node==0.9.0a8 stigmem-plugin-source-attestation==0.1.0
50
+ ```
51
+
52
+ ## Enable
53
+
54
+ Set the plugin gate environment variable to opt in:
55
+
56
+ ```bash
57
+ export STIGMEM_SOURCE_ATTESTATION_ENABLED=1
58
+ ```
59
+
60
+ The default install is inert; source attestation only activates when the
61
+ package is installed, discovered through the `stigmem.plugins` entry point, and
62
+ the operator enables the gate. Enforcement-specific gates such as
63
+ `STIGMEM_SOURCE_ATTESTATION_ENFORCE_ASSERT_VALIDATION` and
64
+ `STIGMEM_SOURCE_ATTESTATION_ENFORCE_FEDERATION_INBOUND` remain opt-in and must
65
+ not be enabled with warn-only mode.
66
+
67
+ ## Disable
68
+
69
+ Unset the plugin gate environment variable, or set it to any value other than
70
+ `1`, `true`, `yes`, or `on`:
71
+
72
+ ```bash
73
+ unset STIGMEM_SOURCE_ATTESTATION_ENABLED
74
+ ```
75
+
76
+ The plugin returns to inert state at the next process start. No data migration
77
+ is required; core source, scope, tenant, and audit enforcement continues to hold
78
+ without plugin participation.
79
+
80
+ ## Test
81
+
82
+ From a Stigmem repository checkout with development dependencies installed:
83
+
84
+ ```bash
85
+ uv run pytest node/tests/plugins/test_source_attestation_plugin_scaffold.py \
86
+ node/tests/plugins/test_source_attestation_plugin_validation.py
87
+ ```
88
+
89
+ The package itself ships no separate test tree; upstream plugin validation
90
+ lives in `node/tests/plugins/`.
91
+
92
+ ## Uninstall
93
+
94
+ ```bash
95
+ pip uninstall stigmem-plugin-source-attestation
96
+ ```
97
+
98
+ Removing the package is sufficient. The gate environment variable becomes moot
99
+ once the entry point is no longer discoverable.
100
+
101
+ ## Project Links
102
+
103
+ - Repository: <https://github.com/eidetic-labs/stigmem>
104
+ - Feature record: <https://github.com/eidetic-labs/stigmem/tree/main/features/source-attestation>
105
+ - Plugin source: <https://github.com/eidetic-labs/stigmem/tree/main/experimental/source-attestation>
106
+ - Issue tracker: <https://github.com/eidetic-labs/stigmem/issues>
@@ -0,0 +1,8 @@
1
+ stigmem_plugin_source_attestation/__init__.py,sha256=YBQ6ZoUBCzantFo-SdzDz0kj-4h_ARC26Y2PPojmdhI,275
2
+ stigmem_plugin_source_attestation/config.py,sha256=Uk8LyNig3hMDdDd1S20zZE6AtrCitEkAh_CddNVW7ig,1743
3
+ stigmem_plugin_source_attestation/handlers.py,sha256=DodZgnBoMpyeKTwlM4uHnpOgJ7lPEnANHpjAML8oMYM,5283
4
+ stigmem_plugin_source_attestation/manifest.py,sha256=Ean8DS_9_9gXjfCCOsSGSrfiM2ifJLmmSlUw9NTilR4,1300
5
+ stigmem_plugin_source_attestation-0.1.0.dist-info/METADATA,sha256=M3y-fOgetcnomA88m9EsTxWJrEDyBxnrnjcB-h0OdRE,3923
6
+ stigmem_plugin_source_attestation-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
7
+ stigmem_plugin_source_attestation-0.1.0.dist-info/entry_points.txt,sha256=OUSYxVhSNsIbv3UNoWu9FVmhJEmhZYx6N-Zkefq25V0,89
8
+ stigmem_plugin_source_attestation-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [stigmem.plugins]
2
+ source-attestation = stigmem_plugin_source_attestation:plugin_manifest