//! Groups: a GitLab-like, single-parent org tree ABOVE apps (Phase 2).
//!
//! Groups are a pure org / RBAC / UI container — they own no resources
//! (scripts/secrets stay app-owned). A `group_admin` on any ancestor is
//! implicitly app_admin on every app/subgroup beneath it; resolution
//! takes the highest effective role across the app's own membership and
//! all ancestor group memberships.
//!
//! See docs/design/groups-and-project-tool.md §5.

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

use crate::{GroupId, ProjectId};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Group {
    pub id: GroupId,
    /// `None` for a root node. Single-parent keeps the tree acyclic.
    pub parent_id: Option<GroupId>,
    /// Instance-global identifier, frozen at creation (a rename/reparent
    /// never rewrites it — the deployment key stays stable).
    pub slug: String,
    pub name: String,
    pub description: Option<String>,
    /// Per-subtree structure version, bumped on every structural mutation
    /// (reparent/rename/delete). Not an authz input.
    pub structure_version: i64,
    /// §7 multi-repo ownership: the project that declaratively manages this
    /// node, or `None` when the node is UI/API-owned (no manifest claims it).
    /// Apps inherit ownership from their nearest claimed ancestor group.
    pub owner_project: Option<ProjectId>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}
