Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d68e0bd
fix(install): preserve local transitive anchors at user scope
danielmeppiel Sep 5, 2026
bb1acf4
Merge current main before publishing #2815
danielmeppiel Sep 5, 2026
e718811
test(architecture): register local scope admission in fixed inventory
danielmeppiel Sep 5, 2026
22024cb
Merge current main before local-path specification reconciliation
danielmeppiel Sep 6, 2026
c2f20a0
spec: reconcile trusted-local source anchoring (#2818)
danielmeppiel Sep 6, 2026
768a4e2
spec: clarify source routing and local replay limits
danielmeppiel Sep 6, 2026
c457d91
fix: require established declaring-source provenance
danielmeppiel Sep 6, 2026
0f0d4b0
docs(spec): prepare corrective minor and exact assessment harness
danielmeppiel Sep 6, 2026
75d0f74
Merge immutable declaring-source provenance correction
danielmeppiel Sep 6, 2026
3069210
test(spec): retain provenance mutation coverage without duplicate guard
danielmeppiel Sep 6, 2026
70b772e
fix(audit): replay canonical current target intent
danielmeppiel Sep 5, 2026
1d4ff88
fix(audit): keep native replay and discovery read-only
danielmeppiel Sep 6, 2026
68015fa
spec: complete corrective v0.2.0 review candidate
danielmeppiel Sep 6, 2026
4878a17
Merge current main for combined fix and corrective-spec validation
danielmeppiel Sep 6, 2026
a036f37
spec: fold corrective review clarifications and evidence limits
danielmeppiel Sep 6, 2026
26c04b8
Integrate bounded corrective-spec review folds
danielmeppiel Sep 6, 2026
f4110c8
test(spec): preserve review evidence and explicit replay limitations
danielmeppiel Sep 6, 2026
a099b69
docs(spec): distinguish original audit cases from review companions
danielmeppiel Sep 6, 2026
300a24a
fix(audit): keep startup and cold replay read-only
danielmeppiel Sep 6, 2026
f5064df
test(cli): preserve JSON guarantees without audit update notices
danielmeppiel Sep 6, 2026
7bb5701
Merge current main into PR 2820 repair baseline
danielmeppiel Sep 7, 2026
92833cf
fix(copilot): rebuild managed instruction aggregates after uninstall
danielmeppiel Sep 7, 2026
32a467c
Merge current main for production closeout
danielmeppiel Sep 7, 2026
216aca2
fix(lifecycle): fold aggregate, audit, and recovery review findings
danielmeppiel Sep 7, 2026
c3e3915
Merge remote-tracking branch 'origin/main' into danielmeppiel-phase-2…
danielmeppiel Sep 7, 2026
824b170
test(architecture): keep aggregate mutation in deterministic inventor…
danielmeppiel Sep 7, 2026
897e15a
fix(alias): reject path-traversing dependency aliases
Danvs60 Sep 7, 2026
38608f4
fix(alias): surface friendly error for traversal aliases
Danvs60 Sep 8, 2026
206d489
test(alias): prove install-phase symlink escape is blocked
Danvs60 Sep 8, 2026
9da1ecd
test(alias): trap ensure_path_within guards end-to-end at install tier
Danvs60 Sep 8, 2026
e845ebf
Refactor install path handling for dependencies
Danvs60 Sep 8, 2026
e2015db
fix(alias): centralize safe destinations without restricting sources
danielmeppiel Sep 8, 2026
1c9029a
Merge contributor follow-up while retaining canonical alias paths
danielmeppiel Sep 8, 2026
2893043
Merge main before alias compatibility validation
danielmeppiel Sep 8, 2026
3bad638
fix(alias): preserve normalized roots and legacy cache preflight
danielmeppiel Sep 8, 2026
ae3099d
fix(alias): preserve remote source anchors and cache replacement
danielmeppiel Sep 8, 2026
0858443
docs(spec): preserve current baseline in inactive corrective draft
danielmeppiel Sep 9, 2026
9167a99
fix(alias): preserve placement and current ref replay after install
danielmeppiel Sep 9, 2026
c5b4a86
test(cache): exercise stale bare fallback under corrupt receipts
danielmeppiel Sep 9, 2026
58190d8
test(lockfile): declare absent alias in dev dependency fixtures
danielmeppiel Sep 9, 2026
a8607b2
docs(spec): isolate inactive corrective foundation after runtime split
danielmeppiel Sep 9, 2026
d1dd63c
Merge current main into alias recovery candidate
danielmeppiel Sep 9, 2026
e6e3191
Merge prospective alias prerequisite for corrective spec reconciliation
danielmeppiel Sep 9, 2026
d22119c
docs(spec): reconcile corrective foundation with prospective alias am…
danielmeppiel Sep 9, 2026
5a0d872
fix(spec): preserve published alias schema identities
danielmeppiel Sep 9, 2026
0eac24f
docs(changelog): name the inactive specification artifact
danielmeppiel Sep 9, 2026
9929f4d
Merge versioned alias schemas without replacing published identities
danielmeppiel Sep 9, 2026
9e5a0eb
docs(spec): reconcile reviewed inactive foundation and schema identities
danielmeppiel Sep 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .apm/architecture/owners/contracts-tooling.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
{
"id": "dependency-identity-materialization",
"decision": "Dependency comparison identity and policy casing vs display-cased materialization path; embedded git URL subpath validation",
"owner": "models/dependency/identity.py + materialization.py + DependencyReference (_check_no_embedded_subpath consumes core/host_providers.py)",
"owner": "models/dependency/identity.py + materialization.py + object_fields.py (alias validation) + deps/apm_resolver.py (remote source-coordinate anchoring) + DependencyReference (_check_no_embedded_subpath consumes core/host_providers.py)",
"selectors": [
"src/apm_cli/models/dependency/identity.py",
"src/apm_cli/models/dependency/materialization.py",
"src/apm_cli/models/dependency/reference.py"
"src/apm_cli/models/dependency/object_fields.py",
"src/apm_cli/models/dependency/reference.py",
"src/apm_cli/deps/apm_resolver.py"
],
"guards": ["contracts-tooling-dependency-identity", "contracts-tooling-policy-identity"]
},
Expand Down Expand Up @@ -60,7 +62,7 @@
{
"id": "read-only-lockfile-path",
"decision": "Lockfile read path, timestamp emission, and reproducible fallback",
"owner": "deps/lockfile.py (resolve_lockfile_path_for_read, LockFile.write, resolve_reproducible_timestamp)",
"owner": "deps/lockfile.py (resolve_lockfile_path_for_read, LockFile.write, resolve_reproducible_timestamp, LockedDependency alias projection)",
"selectors": ["src/apm_cli/deps/lockfile.py"],
"guards": [
"contracts-tooling-lockfile-read",
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Inactive `specs/openapm-v0.2.md` corrective draft for local-source admission and read-only current-intent audit; v0.1 remains active, runtime work is tracked in #2919 and #2923, and human ratification remains pending. (#2820)
- gh-aw's shared APM import now supports `token-source: github-token`; after consumers re-vendor the workflow, its read-only current-repository identity can fetch same-repository private packages, while `cascade` remains the default and cross-repository packages still require a dedicated token or GitHub App. (#2706)
- OpenAPM v0.1 adds `req-pl-018` for dependency-policy identity casing and amends `req-rs-016` clause (3), the Section 6.4 merge rules, and the Section 6.5 pattern grammar so repository identity and policy matching cannot diverge; Section 11.2 item 6 now requires the per-host case rule in `CONFORMANCE.md`. (#2706)

Expand All @@ -20,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Security

- Dependency aliases now reject `.` and `..`, require contained destinations, and persist placement for replay and cleanup; documented in `specs/openapm-v0.1.md` (`req-mf-025`). [Review alias migration and reinstall artifacts](https://microsoft.github.io/apm/troubleshooting/migration/#rejected-dependency-aliases). - by @Danvs60 (#2901)
- The shared gh-aw APM pack job now declares `contents: read` (previously `permissions: {}`), the minimum the explicit built-in-token path needs. No write scope is added, and the token is not forwarded to restore or agent jobs. (#2706)
- Dependency policy `allow`, `deny`, and exact `require` matching now follows canonical owner/repository casing, fixing mixed-case blocks and deny fail-open behavior while retaining lazy shared required-package lookup. APM 0.30.0 and earlier match patterns byte-exactly against the lowercased identity; lowercase patterns keep matching in every release, so drop workaround duplicates only after every runner uses a release carrying this fix. (#2706)

Expand Down
59 changes: 57 additions & 2 deletions CONFORMANCE.json
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,61 @@
"tests/spec_conformance/test_manifest_reqs.py::test_consumer_preserves_registry_identity_on_structured_rewrite"
]
},
{
"conformance_class": "consumer",
"id": "req-mf-025",
"keyword": "MUST",
"section": "4.3.2",
"status": "active",
"test_count": 45,
"tests": [
"tests/spec_conformance/test_alias_reqs.py::test_absent_alias_is_not_inferred_from_inventory_name",
"tests/spec_conformance/test_alias_reqs.py::test_alias_rejects_symlink_destination[outside]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_rejects_symlink_destination[root]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[ \\r..\\t-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[ \\tMy.Safe\\n-True-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[ \\t\\n-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[.-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[..-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[../escape-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[..\\n-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[.safe-True-True]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[1-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[foo..bar-True-True]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[my-skill.v2-True-True]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[safe.-True-True]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[safe/name-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[safe\\n-True-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_schemas_distinguish_input_from_canonical_output[safe\\ninside-False-False]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[git- \\tMy.Safe\\n]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[git-.safe]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[git-None]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[git-foo..bar]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[git-my-skill.v2]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[git-safe.]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[local- \\tMy.Safe\\n]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[local-.safe]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[local-None]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[local-foo..bar]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[local-my-skill.v2]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[local-safe.]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[registry- \\tMy.Safe\\n]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[registry-.safe]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[registry-None]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[registry-foo..bar]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[registry-my-skill.v2]",
"tests/spec_conformance/test_alias_reqs.py::test_alias_survives_lock_replay_without_changing_source[registry-safe.]",
"tests/spec_conformance/test_alias_reqs.py::test_invalid_lock_alias_guidance_repairs_the_lock_not_the_manifest",
"tests/spec_conformance/test_alias_reqs.py::test_lock_alias_rejects_invalid_destination_names[%2e%2e]",
"tests/spec_conformance/test_alias_reqs.py::test_lock_alias_rejects_invalid_destination_names[../escape]",
"tests/spec_conformance/test_alias_reqs.py::test_lock_alias_rejects_invalid_destination_names[..]",
"tests/spec_conformance/test_alias_reqs.py::test_lock_alias_rejects_invalid_destination_names[.]",
"tests/spec_conformance/test_alias_reqs.py::test_lock_alias_rejects_invalid_destination_names[1]",
"tests/spec_conformance/test_alias_reqs.py::test_lock_alias_rejects_invalid_destination_names[]",
"tests/spec_conformance/test_alias_reqs.py::test_lock_alias_rejects_invalid_destination_names[foo/../bar]"
]
},
{
"conformance_class": "governance",
"id": "req-pl-001",
Expand Down Expand Up @@ -1426,7 +1481,7 @@
"spec_version": "v0.1.1",
"summary_by_class": {
"consumer": {
"active": 90,
"active": 91,
"skipped": 1,
"unbound": 0,
"xfail": 0
Expand All @@ -1450,5 +1505,5 @@
"xfail": 0
}
},
"total_requirements": 122
"total_requirements": 123
}
3 changes: 2 additions & 1 deletion CONFORMANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Repository-coordinate segments are case-insensitive for `github.com`, GitHub Ent
| Class | Active | Skipped | Xfail | Unbound |
|-------|-------:|--------:|------:|--------:|
| Producer | 12 | 0 | 0 | 0 |
| Consumer | 90 | 1 | 0 | 0 |
| Consumer | 91 | 1 | 0 | 0 |
| Registry | 1 | 0 | 0 | 0 |
| Governance | 18 | 0 | 0 | 0 |

Expand Down Expand Up @@ -87,6 +87,7 @@ Repository-coordinate segments are case-insensitive for `github.com`, GitHub Ent
| [req-mf-022](docs/src/content/docs/specs/openapm-v0.1.md#req-mf-022) | MUST | 4.3.2 | consumer | active | 2 | - |
| [req-mf-023](docs/src/content/docs/specs/openapm-v0.1.md#req-mf-023) | MUST | 4.5 | consumer | active | 1 | - |
| [req-mf-024](docs/src/content/docs/specs/openapm-v0.1.md#req-mf-024) | MUST | 4.3.2 | consumer | active | 1 | - |
| [req-mf-025](docs/src/content/docs/specs/openapm-v0.1.md#req-mf-025) | MUST | 4.3.2 | consumer | active | 45 | - |
| [req-pl-001](docs/src/content/docs/specs/openapm-v0.1.md#req-pl-001) | MUST | 6.1 | governance | active | 1 | - |
| [req-pl-002](docs/src/content/docs/specs/openapm-v0.1.md#req-pl-002) | MUST | 6.2 | governance | active | 1 | - |
| [req-pl-003](docs/src/content/docs/specs/openapm-v0.1.md#req-pl-003) | MUST | 6.4 | governance | active | 1 | - |
Expand Down
5 changes: 5 additions & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export default defineConfig({
'/spec': '/apm/specs/openapm-v01/',
'/spec/latest': '/apm/specs/openapm-v01/',
'/spec/v0.1': '/apm/specs/openapm-v01/',
// Exact revision slug is pinned; a later patch needs a distinct artifact.
// Keep /spec and /spec/latest unchanged until actual ratification.
'/spec/v0.2': '/apm/specs/openapm-v020/',
'/spec/v0.2.0': '/apm/specs/openapm-v020/',
},
integrations: [
sitemap(),
Expand Down Expand Up @@ -295,6 +299,7 @@ export default defineConfig({
// (/spec, /spec/v0.1, /spec/latest) bridge this in the
// redirects block above for external citers.
{ label: 'OpenAPM v0.1', slug: 'specs/openapm-v01' },
{ label: 'OpenAPM v0.2.0 (draft)', slug: 'specs/openapm-v020' },
{ label: 'Conformance', slug: 'specs/conformance' },
],
},
Expand Down
4 changes: 4 additions & 0 deletions docs/public/specs/manifests/openapm-v0.1.requirements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ requirements:
keyword: MUST
section: "4.3.2"
conformance_class: consumer
- id: req-mf-025
keyword: MUST
section: "4.3.2"
conformance_class: consumer
- id: req-ext-001
keyword: MUST
section: "4.1"
Expand Down
Loading
Loading