data-olympus 0.3.4__tar.gz → 0.3.5__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.
- {data_olympus-0.3.4 → data_olympus-0.3.5}/CHANGELOG.md +28 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/PKG-INFO +1 -1
- {data_olympus-0.3.4 → data_olympus-0.3.5}/pyproject.toml +1 -1
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/auth.py +26 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/tools_write.py +12 -4
- {data_olympus-0.3.4 → data_olympus-0.3.5}/.gitignore +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/LICENSE +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/NOTICE +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/README.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/SPEC.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/benchmarks/README.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/bin/_kb_detect_workspace.sh +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/bin/_kb_enforce.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/bin/_kb_fallback.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/bin/kb +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/bin/kb-enforce-hook +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/bin/opencode/data-olympus-gate.ts +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/deploy/k8s/README.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/deploy/k8s/read-replica/README.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/docs/releases/README.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/example-bundle/projects/acme-app/README.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/example-bundle/projects/acme-app/components/api/README.md +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/__init__.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/audit_log.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/audit_trailers.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/cli/__init__.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/cli/import_cmd.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/cli/indexgen.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/cli/main.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/cli/report_cmd.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/config.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/cooccurrence.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/dedup.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/durable.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/embeddings.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/enforce_policy.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/format/__init__.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/format/document.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/format/frontmatter.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/format/lint.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/format/validate.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/git_ops.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/health.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/importer/__init__.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/importer/adr.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/importer/flat.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/importer/model.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/importer/okf.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/importer/run.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/importer/stamp.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/index.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/markdown_parse.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/models.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/onboarding.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/onboarding_inflight.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/onboarding_playbook.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/pending.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/principals.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/prompts.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/push_queue.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/query_expansion.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/rate_limit.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/refresh.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/report.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/rest_api.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/safe_id.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/search_gate.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/search_shortcut.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/server.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/session_metrics.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/setup_wizard.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/thin_pointer.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/tools_audit.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/tools_enforce.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/tools_onboarding.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/tools_read.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/trigram.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/viewer/__init__.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/viewer/generator.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/worktrees.py +0 -0
- {data_olympus-0.3.4 → data_olympus-0.3.5}/src/data_olympus/write_gate.py +0 -0
|
@@ -12,6 +12,34 @@ This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
## [0.3.5] - 2026-07-06
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Ambiguous rejection reason for writes outside the deployment's indexed
|
|
20
|
+
prefixes.** `kb_propose_edit` (and `kb_propose_memory`) rejected a
|
|
21
|
+
well-formed, non-malicious path outside `KB_INDEXED_PREFIXES` with the same
|
|
22
|
+
opaque reason string (`traversal_or_excluded` / `not_md_or_excluded`) used
|
|
23
|
+
for an actual traversal or control-character attempt. A syntactically fine
|
|
24
|
+
path outside the configured prefixes is an ordinary deployment-configuration
|
|
25
|
+
fact, not a structural or security rejection - conflating the two sent an
|
|
26
|
+
operator hunting for a nonexistent traversal bug during a company-knowledge
|
|
27
|
+
KB audit session (`operator/laptop.md`, readable and indexed for search,
|
|
28
|
+
came back rejected on write with no indication it was simply outside the
|
|
29
|
+
deployment's writable-prefix allowlist). `rejected_path_not_indexable`
|
|
30
|
+
responses (and audit events) now carry a specific reason:
|
|
31
|
+
`structurally_invalid` (empty/control-chars/absolute/traversal/excluded
|
|
32
|
+
segment), `not_markdown`, or `not_in_indexed_prefixes`.
|
|
33
|
+
- Investigated the same session's second report (a `rejected_stale_base`
|
|
34
|
+
resolve appearing to "leak" its path lock) and confirmed it is **not a
|
|
35
|
+
bug**: `restore_resolve` deliberately keeps the path lock held after a
|
|
36
|
+
gate rejection so the operator's still-pending proposal can't be clobbered
|
|
37
|
+
by a concurrent write to the same path (documented behavior, hardened
|
|
38
|
+
across multiple rounds of review). `reject`ing the stale entry (which does
|
|
39
|
+
release the lock) and re-proposing fresh, exactly what that session did, is
|
|
40
|
+
the correct and only intended recovery for a pending entry with a
|
|
41
|
+
permanently-wrong base marker - there was nothing to fix.
|
|
42
|
+
|
|
15
43
|
## [0.3.4] - 2026-07-05
|
|
16
44
|
|
|
17
45
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: data-olympus
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Governance-grade knowledge-base format (OKF-compatible) plus CLI and single-writer MCP server
|
|
5
5
|
Project-URL: Homepage, https://github.com/knaisoma/data-olympus
|
|
6
6
|
Project-URL: Repository, https://github.com/knaisoma/data-olympus
|
|
@@ -95,6 +95,32 @@ def is_writable_path(target_path: str) -> bool:
|
|
|
95
95
|
return any(canonical.startswith(p) for p in indexed_prefixes())
|
|
96
96
|
|
|
97
97
|
|
|
98
|
+
def path_rejection_reason(raw_target_path: str) -> str:
|
|
99
|
+
"""Why a path fails :func:`is_writable_path`, for a caller that already knows
|
|
100
|
+
it does. Three distinct causes were previously collapsed into one opaque
|
|
101
|
+
reason string (``not_md_or_excluded`` / ``traversal_or_excluded``), which
|
|
102
|
+
reads identically whether the path was a malicious traversal attempt or a
|
|
103
|
+
perfectly legitimate path outside the deployment's configured
|
|
104
|
+
``KB_INDEXED_PREFIXES`` - the latter is an ordinary, expected outcome for any
|
|
105
|
+
deployment whose repo layout has top-level directories beyond the generic
|
|
106
|
+
default (see ``indexed_prefixes()``), not a security event, and conflating
|
|
107
|
+
the two sent at least one operator hunting for a traversal bug that was
|
|
108
|
+
actually a missing ``KB_INDEXED_PREFIXES`` entry.
|
|
109
|
+
|
|
110
|
+
Returns one of: ``structurally_invalid`` (empty/control-chars/absolute/
|
|
111
|
+
traversal/excluded-segment - :func:`normalize_target_path` rejected it),
|
|
112
|
+
``not_markdown``, or ``not_in_indexed_prefixes`` (a syntactically fine path
|
|
113
|
+
outside every configured prefix - a deployment-configuration gap, not a
|
|
114
|
+
structural or security rejection).
|
|
115
|
+
"""
|
|
116
|
+
canonical = normalize_target_path(raw_target_path)
|
|
117
|
+
if canonical is None:
|
|
118
|
+
return "structurally_invalid"
|
|
119
|
+
if not canonical.endswith(".md"):
|
|
120
|
+
return "not_markdown"
|
|
121
|
+
return "not_in_indexed_prefixes"
|
|
122
|
+
|
|
123
|
+
|
|
98
124
|
def safe_join_under_root(root: str, target_path: str) -> str | None:
|
|
99
125
|
"""Join ``target_path`` under ``root`` and return the absolute path only when
|
|
100
126
|
it resolves to exactly that lexical location inside ``root``; else return None.
|
|
@@ -15,6 +15,7 @@ from data_olympus.auth import (
|
|
|
15
15
|
PathBlocklist,
|
|
16
16
|
is_writable_path,
|
|
17
17
|
normalize_target_path,
|
|
18
|
+
path_rejection_reason,
|
|
18
19
|
safe_join_under_root,
|
|
19
20
|
)
|
|
20
21
|
from data_olympus.format.frontmatter import parse_frontmatter
|
|
@@ -486,11 +487,12 @@ def kb_propose_memory_fn(
|
|
|
486
487
|
|
|
487
488
|
# 1. Structural rule (cheap).
|
|
488
489
|
if not is_writable_path(target_path):
|
|
490
|
+
reason = path_rejection_reason(target_path)
|
|
489
491
|
_emit_audit(audit_log, **{**audit_base, "status": "rejected_path_not_indexable",
|
|
490
|
-
"reason":
|
|
492
|
+
"reason": reason})
|
|
491
493
|
return ProposeResponse(
|
|
492
494
|
status="rejected_path_not_indexable",
|
|
493
|
-
reason=
|
|
495
|
+
reason=reason,
|
|
494
496
|
target_path=target_path,
|
|
495
497
|
)
|
|
496
498
|
|
|
@@ -657,9 +659,15 @@ def kb_propose_edit_fn(
|
|
|
657
659
|
}
|
|
658
660
|
canonical = normalize_target_path(target_path)
|
|
659
661
|
if canonical is None or not is_writable_path(canonical):
|
|
660
|
-
|
|
662
|
+
# audit_base["reason"] otherwise carries the caller's edit rationale;
|
|
663
|
+
# for this terminal rejection (nothing is written) it is overwritten
|
|
664
|
+
# with the machine rejection cause instead, since that is what an
|
|
665
|
+
# operator reading the audit log needs to see here.
|
|
666
|
+
rejection_reason = path_rejection_reason(target_path)
|
|
667
|
+
_emit_audit(audit_log, **{**audit_base, "status": "rejected_path_not_indexable",
|
|
668
|
+
"reason": rejection_reason})
|
|
661
669
|
return ProposeResponse(status="rejected_path_not_indexable",
|
|
662
|
-
reason=
|
|
670
|
+
reason=rejection_reason,
|
|
663
671
|
target_path=target_path)
|
|
664
672
|
# From here on operate ONLY on the canonical path: classification, blocklist,
|
|
665
673
|
# the pending record, the filesystem join, and ``git add`` must all agree with
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_olympus-0.3.4 → data_olympus-0.3.5}/example-bundle/projects/acme-app/components/api/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|