Portability: import replaces a content type's fields without validation, skips entry checks, and drops the lifecycle
- Dominant language
- C#
- Stars
- 6
- Forks
- 7
- Avg merge
- 4h 42m
- Merged PRs (30d)
- 307
Description
`POST /api/portability/import` updates an existing content type by overwriting it with the bundle's copy, `match.Fields = type.Fields` (`BarakoCMS.Portability/ImportEndpoint.cs:59-66`), and stores a new type the same way (`ImportEndpoint.cs:78-92`). It never calls `IContentTypeValidatorService`, which create (`barakoCMS/Features/ContentType/Create/Endpoint.cs:90`), add field and blueprint apply all run.
That lets through:
- Field lists create refuses: an unknown field type, a reference with no target, duplicate names under different casing, no fields at all.
- A required field with no default on a type that already has entries, which add field refuses for this exact reason (`barakoCMS/Features/ContentType/AddField/Endpoint.cs:72`).
- A sensitivity change with none of the guards in `barakoCMS/Features/ContentType/SetFieldSensitivity/Endpoint.cs:23-45`. Lowering a field to Public needs no `acknowledgeDisclosure` and writes no disclosure audit. Raising one leaves its value in `SearchText`, so anonymous search still matches it.
- The lifecycle. Export writes the whole `ContentTypeDefinition`, `Lifecycle` included (`barakoCMS/Models/ContentTypeDefinition.cs:63`), but the update branch never copies it and the create branch never sets it. A type with approval states comes back with the default three.
Entries are written straight through `IContentWriter.CreateAsync` (`ImportEndpoint.cs:152-153`) with no `IContentValidatorService` pass and no lifecycle hooks, where create, update and rollback run both. A bundle can store entries missing required fields, values of the wrong type, dangling references, duplicate slugs, or a parent loop a hook would refuse.
### Why it is a bug
Import is the one route that writes a whole schema and its content, and it is the least checked of all of them. An export followed by an import is meant to reproduce a type, and it silently does not.
### The fix
Import runs what create runs: `Validate` and `ValidateLifecycle` on every type, the add field rule for required fields on a type with entries, and a refusal (or the same acknowledge flag) for a sensitivity change, with the search text rebuilt the way `SetFieldSensitivity` does it. `Lifecycle` is carried on both branches. Each entry goes through `IContentValidatorService` and the lifecycle runner, and failures are reported per record. A dry run reports the same errors without writing.
### Where it lives
Portability module, calling the core validators.
### Compatibility
Released. A bundle with an invalid schema or invalid entries that imports today is refused after this. That tightens what the endpoint accepts, so it moves `ApiContract.Version` and rides the contract bump already in flight for 4.2.0 (#861, #867). A bundle exported from a valid instance imports as before. The config engine in #921 replaces this module later; this fix does not wait for it.
### Done when
- Importing a bundle whose existing type now has a field of type `nonsense` is a 400 and leaves the stored type unchanged. Today it answers 200 and stores it, so the test fails before the fix.
- Exporting then importing a type with a custom lifecycle keeps the lifecycle, with a test that fails before the fix.
- A bundle that lowers a Sensitive field to Public without acknowledgement is refused, and one that raises a field leaves no value matchable by anonymous search.
- A record missing a required field is reported and not stored.
Found in the architecture sweep of 15 September 2026.
Contributor guide
Research direction
Start with BarakoCMS.Portability/ImportEndpoint.cs and compare its type and entry writes with the validator and lifecycle calls in the cited ContentType and entry endpoints. Trace the existing sensitivity, search-text, and contract-version behavior before running the portability tests. Done means invalid schemas and entries are rejected without writes, lifecycle and sensitivity rules are preserved, errors are reported per record, and dry-run reports the same failures.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api, backend, search, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100