feat(cli): files kind in manifest + reconcile (§11.6 files C4)

- manifest: add CollectionKind::Files (+ "files" in as_str()); the
  string-or-table `collections` form now accepts { name, kind = "files" }.
- apply_service: add "files" to COLLECTION_KINDS. The rest of the
  reconcile (CollectionSpec, diff_collections, validate_bundle,
  state_token, the app-owner rejection) is already kind-generic.
- `pic collections ls` shows the files kind with no code change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-30 19:48:16 +02:00
parent e7c0485dbf
commit 17221a2683
2 changed files with 6 additions and 2 deletions

View File

@@ -110,7 +110,7 @@ fn default_collection_kind() -> String {
}
/// The shared-collection kinds the apply engine accepts.
const COLLECTION_KINDS: &[&str] = &["kv", "docs"];
const COLLECTION_KINDS: &[&str] = &["kv", "docs", "files"];
#[derive(Debug, Clone, Deserialize)]
pub struct BundleScript {

View File

@@ -269,6 +269,7 @@ pub struct ManifestGroup {
pub enum CollectionKind {
Kv,
Docs,
Files,
}
impl CollectionKind {
@@ -277,6 +278,7 @@ impl CollectionKind {
match self {
Self::Kv => "kv",
Self::Docs => "docs",
Self::Files => "files",
}
}
}
@@ -726,7 +728,8 @@ mod tests {
// `{ name, kind }` table sets an explicit kind. Both coexist.
let m = Manifest::parse(
"[group]\nslug = \"acme\"\nname = \"ACME\"\n\n\
collections = [\"catalog\", { name = \"articles\", kind = \"docs\" }]\n",
collections = [\"catalog\", { name = \"articles\", kind = \"docs\" }, \
{ name = \"assets\", kind = \"files\" }]\n",
)
.expect("string-or-table collections must parse");
assert_eq!(
@@ -734,6 +737,7 @@ mod tests {
vec![
("catalog".to_string(), "kv".to_string()),
("articles".to_string(), "docs".to_string()),
("assets".to_string(), "files".to_string()),
]
);
// An app manifest carrying `collections` is rejected (no such field +