Commit Graph

3 Commits

Author SHA1 Message Date
MechaCat02
0078ae8b26 feat(apply): §6 M1 — declarative group create (directory-nesting parentage)
Lift "groups must pre-exist" for the tree apply: a `[group]` node now carries a
declared parent (inferred from directory nesting) and `pic apply --dir` creates
the ones the server lacks, in the same transaction.

Wire: `TreeNode` gains `parent`/`name`/`description` (`#[serde(default)]` — a
pre-§6 CLI still reconciles existing groups). `discover::build_tree` computes a
group's parent as the nearest ancestor directory holding a `[group]` (topmost →
the repo's `[project] parent_group` attach point, else instance root) and emits
nodes parents-first by directory depth.

Server: `apply_tree` runs a Phase 0 (`create_missing_groups_tx`) that
resolves-or-creates every group node IN the tx (a same-tree parent resolved
before its child via the new `group_repo::{create_group_tx,
read_group_id_by_slug_tx}`), under the coarse `GROUP_STRUCTURAL_LOCK_KEY` (taken
only when creating), enforcing the attach-point ceiling + RBAC
(`InstanceCreateGroup` / `GroupAdmin(parent)`) per create. A created group is
CLAIMED in Phase A alongside existing ones (`decide_group_claim` → `Claim`).
`prepare_tree` now takes a caller-supplied `resolved_ids` map and returns a
`to_create` list the plan path previews (empty current → full-create plan,
ownership `claim`); a to-create group's token part equals its post-create part
so plan/apply tokens match across a create. `validate_bundle_for` takes
`is_group: bool` (a to-create group has no id yet); `authz_tree` skips a
to-create group (its create authz is the service gate, not an existing-group
capability).

Reparent of a diverged existing group + the detect-and-refuse flags are M2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 20:07:03 +02:00
MechaCat02
b33c87e5c4 feat(cli): [project] manifest block, --takeover, groups ls owner column
Makes §7 ownership usable end to end from the CLI.

- manifest: a `[project]` block (slug + optional name), independent of the
  [app]/[group] XOR; threaded onto every apply from the repo. --dir reads it
  from the tree ROOT's picloud.toml (a [project] elsewhere is ignored with a
  note).
- client: apply_node/apply_tree carry project + takeover; the 409 branch now
  surfaces the server message verbatim (covers StateMoved AND OwnershipConflict,
  both self-contained). New groups_list_with_owner captures the owner slug.
- pic apply --takeover flag; pic groups ls gains an `owner` column (the owning
  project's slug, or — when unclaimed).
- server: /api/v1/admin/groups now returns each group flattened with its owner
  slug (via list_with_owner) — the shared Group deserialize ignores the extra
  field, so pic groups tree / the dashboard are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 20:46:09 +02:00
MechaCat02
1662d7806a feat(cli): nested-manifest discovery + pic plan/apply --dir tree mode (Phase 5 C4)
Phase 5 C4. `pic plan --dir <root>` / `pic apply --dir <root>` discover every
`picloud.toml` under a directory (groups + apps), assemble the wire tree
bundle, and drive the C3 `/tree/{plan,apply}` endpoints — a whole project
subtree reconciled and reviewed as one unit.

  * New `discover` module: recursive walk (skips `.picloud`/`.git`/`scripts`/
    `target`), one node per manifest, app/group inferred from the manifest;
    rejects a duplicate (kind, slug). On-disk nesting is organizational — the
    server resolves ancestry from its own group tree.
  * `client`: `plan_tree`/`apply_tree` + `TreePlanDto`/`NodePlanDto`. `pic plan
    --dir` renders a per-node diff table and records ONE tree bound-token under
    a `<tree>` linkstate marker; `pic apply --dir` replays it (force/`--yes`/
    prune apply tree-wide). `--dir` conflicts with `--file`.

Live-validated: a nested tree (root group dir + nested app dir, app route bound
to the group's inherited script) → `pic plan --dir .` shows both nodes' changes
→ `pic apply --dir .` applies all in one tx → re-plan all-noop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:25:29 +02:00