generated from coulomb/repo-seed
145 lines
5.4 KiB
Markdown
145 lines
5.4 KiB
Markdown
# CMIS Profiled Access Points Implementation
|
|
|
|
Date: 2026-05-06
|
|
|
|
Status: Browser Binding MVP implemented.
|
|
|
|
## Implemented Slice
|
|
|
|
`src/kontextual_engine/core/cmis.py` defines the CMIS profile and access-point
|
|
boundary used by the future API adapter:
|
|
|
|
- `CMISBinding`
|
|
- `CMISCapability`
|
|
- `CMISAction`
|
|
- `CMISAccessProfile`
|
|
- `CMISAccessPoint`
|
|
- `CMISDomainMapper`
|
|
- `CMISObjectProjection`
|
|
|
|
The layer is intentionally small. It decides whether a CMIS action is allowed
|
|
for a profile and whether an engine asset may be exposed through an access
|
|
point. It does not implement CMIS routes and does not duplicate asset storage,
|
|
metadata, relationship, policy, or audit services.
|
|
|
|
## Built-In Profiles
|
|
|
|
- `readonly-browser`: Browser Binding read profile over public/internal assets.
|
|
- `governed-authoring`: Browser Binding profile with selected create/update
|
|
and content stream mutations.
|
|
- `admin-export`: service-account-only export profile with broad visibility.
|
|
- `compat-tck`: Browser Binding profile intended for selected OpenCMIS TCK
|
|
compatibility tests.
|
|
|
|
## Enforcement Boundary
|
|
|
|
Profiles can restrict exposure by:
|
|
|
|
- CMIS capability,
|
|
- mutation allowance,
|
|
- actor type,
|
|
- sensitivity,
|
|
- asset type,
|
|
- topic,
|
|
- source system,
|
|
- metadata deny rules.
|
|
|
|
Decisions return existing `PolicyDecision` objects so later CMIS routes can
|
|
emit compatible diagnostics and audit records without inventing another policy
|
|
model.
|
|
|
|
## Mapper Slice
|
|
|
|
`CMISDomainMapper` projects existing engine state into CMIS-shaped envelopes:
|
|
|
|
- repository info and CMIS 1.1 Browser Binding capability flags,
|
|
- base type definitions for document, folder, relationship, policy, item, and
|
|
secondary,
|
|
- engine assets as CMIS document projections,
|
|
- representation metadata as content stream descriptors,
|
|
- asset versions as CMIS version properties,
|
|
- relationship primitives as CMIS relationship objects,
|
|
- profile-derived allowable actions.
|
|
|
|
The mapper returns `None` for assets or relationships that the access-point
|
|
profile must not expose. It does not fetch from repositories directly; callers
|
|
provide the asset, representations, versions, metadata records, and
|
|
relationships they have already authorized or loaded.
|
|
|
|
## Browser Binding MVP Slice
|
|
|
|
The service exposes profile-scoped Browser Binding MVP routes:
|
|
|
|
- `GET /cmis`
|
|
- `GET /cmis/{access_point_id}/browser`
|
|
- `GET /cmis/{access_point_id}/browser/types`
|
|
- `GET /cmis/{access_point_id}/browser/children`
|
|
- `GET /cmis/{access_point_id}/browser/object/{object_id}`
|
|
- `GET /cmis/{access_point_id}/browser/content/{object_id}`
|
|
- `GET /cmis/{access_point_id}/browser/query`
|
|
- `GET /cmis/{access_point_id}/browser/relationships`
|
|
- `GET /cmis/{access_point_id}/browser/changes`
|
|
|
|
The MVP supports repository info, type definitions, synthetic root children,
|
|
object reads, content stream descriptors, a constrained document query subset,
|
|
relationship objects, and audit-backed change entries. Unsupported query
|
|
grammar returns structured diagnostics.
|
|
|
|
## Governed Authoring Slice
|
|
|
|
The Browser Binding adapter now exposes selected mutation routes for profiles
|
|
that allow authoring:
|
|
|
|
- `POST /cmis/{access_point_id}/browser/document`
|
|
- `POST /cmis/{access_point_id}/browser/object/{object_id}/properties`
|
|
- `POST /cmis/{access_point_id}/browser/object/{object_id}/content`
|
|
- `POST /cmis/{access_point_id}/browser/object/{object_id}/delete`
|
|
|
|
These routes delegate to existing engine services:
|
|
|
|
- document creation uses `AssetRegistryService.create_asset`,
|
|
- property updates add governed metadata records,
|
|
- content stream updates add asset representations and content-change versions,
|
|
- delete requests transition the asset lifecycle to `delete_requested`.
|
|
|
|
Read-only profiles reject the same mutations with CMIS-shaped authorization
|
|
diagnostics before touching engine services.
|
|
|
|
## ACL And Redaction Slice
|
|
|
|
The Browser Binding adapter now projects profile-derived ACLs through
|
|
`GET /cmis/{access_point_id}/browser/acl/{object_id}`. ACL entries are derived
|
|
from the access profile and actor context:
|
|
|
|
- visible objects grant the current actor `cmis:read`,
|
|
- authoring profiles also project `cmis:write` and `cmis:delete`,
|
|
- public objects include a read-only `anyone` ACE,
|
|
- hidden objects return `not found` rather than partial metadata.
|
|
|
|
Relationship listings and change logs now apply the same asset visibility gates
|
|
as object reads. This prevents indirect leakage of confidential or restricted
|
|
asset IDs through relationship targets or audit-backed change entries.
|
|
|
|
## Fixture And Optional TCK Integration
|
|
|
|
CMIS fixtures now act as active compatibility contracts:
|
|
|
|
- `examples/cmis/capability-fixtures.json` defines profile expectations and
|
|
capability groups,
|
|
- `tests/cmis/test_cmis_fixture_integration.py` compares those expectations to
|
|
implemented profiles and access-point shapes,
|
|
- `tests/cmis/opencmis-tck/tck-subset-map.json` maps fixture capability groups
|
|
to selected OpenCMIS TCK groups,
|
|
- `tests/cmis/opencmis-tck/tck-result-template.json` captures optional TCK
|
|
result summaries and known capability gaps.
|
|
|
|
The default Python suite validates the fixture/TCK mapping without requiring
|
|
Java or Maven. Actual OpenCMIS TCK execution remains opt-in.
|
|
|
|
Route-level tests are present but skip when the optional FastAPI/httpx service
|
|
dependencies are not installed. Runtime-level Browser Binding tests cover the
|
|
same behavior in the default Python test suite.
|
|
|
|
Deployment and compatibility posture are documented in
|
|
`docs/cmis-deployment-compatibility.md`.
|