docs(spec): defer per-profile access control to app-access-control

- v1: any queue:submit user may use any profile; listing reuses cluster:view
- app:use / app:view design kept in the brief and moved to the new backlog
  item app-access-control (depends on rbac-persistence for API grants)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-13 03:31:00 +00:00
parent 863ba98ac8
commit e48d36054d
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
3 changed files with 45 additions and 43 deletions

View file

@ -229,7 +229,7 @@ fits XCE's LSF-style job model.
(`XCE_APP_ANN_CFD_ORG_SOLVER_FAMILY`). `xceadmin` rejects two
annotation keys (or two params) that convert to the same name.
- Limits on count and size, so a profile cannot bloat every job's env.
- Visible to every `app:view` holder: no secrets (the secret-name
- Visible to every user who can view profiles: no secrets (the secret-name
warning applies). All are exported in v1; an opt-out only if
needed.
- `env` vs annotations vs params: `env` is a variable the application
@ -260,30 +260,25 @@ fits XCE's LSF-style job model.
variables, lower limits) and override a profile `rusage` default, but not
change or remove anything else. Anything else is rejected with a clear
error.
- **Access by RBAC permission.** No new access mechanism; this follows the
existing named-instance pattern (user decision, 2026-09-29: fold profile RBAC
into this spec). Today, `queue:submit` scoped to `type: queue`,
`values: [normal, priority]` in `config/rbac.yaml` is enforced by
`GetRequireResourcePermission` in `controllers/jobs.go:1402-1409`. Profiles add:
- **Permissions:** `app:use` (submit a job with a profile) and `app:view` (list
and inspect profiles).
- **Scope:** a new `app` scope type whose values are profile names, or `all`.
- **Checks:**
- Job create checks `app:use` alongside, and independent of, `queue:submit`.
- Job restart (`POST /:jobids/restart`, which today checks only
`queue:submit`) re-checks `app:use` for the job's profile.
- Listing profiles checks `app:view`.
- **Defaults:** `rbac.yaml` gets defaults, for example `basic_user` →
`app:use` on the default profile, and `app:view` on `all`.
- **The current default profile is always usable** (decided 2026-10-12):
anyone with `queue:submit` has an implicit `app:use` on the profile
`default_application` names (or the built-in `default`), so plain
submits never break when an admin repoints the default.
- **Role API:** role creation and update accept the new scope type.
- **Bypass:** `cluster_admin` keeps the single existing bypass; no new bypass
path.
- **Persistence:** API-made grants are subject to the `rbac-persistence` gap
until that spec lands.
- **Access control is deferred** (user decision, 2026-10-12): v1 has no
per-profile permission. Any user who may submit (`queue:submit`) may use
any profile; listing and showing profiles reuses the existing
`cluster:view` permission (profiles are cluster configuration). The
design recorded below moves to the backlog spec `app-access-control`,
kept here so it is not lost:
- permissions `app:use` (submit with a profile) and `app:view` (list and
inspect profiles), a new `app` scope type whose values are profile
names or `all`, following the named-instance pattern of `queue:submit`
(`config/rbac.yaml`, `GetRequireResourcePermission`,
`controllers/jobs.go:1402-1409`);
- checks on job create (alongside, and independent of, `queue:submit`),
on job restart (re-check for the job's profile) and on listing;
- `rbac.yaml` defaults (`basic_user` → `app:use` on the default profile,
`app:view` on `all`); the current default profile always usable with
`queue:submit` (implicit `app:use`), so plain submits never break when
the default is repointed; aliases checked against the target profile;
- role API accepts the new scope type; `cluster_admin` keeps the single
existing bypass; API-made grants depend on `rbac-persistence`.
- **Queues and profiles are orthogonal** (user decision, 2026-09-29).
- **Queues** own scheduling policy: which jobs are considered and in what
order, priority, scheduling limits, and host partitioning.
@ -293,8 +288,9 @@ fits XCE's LSF-style job model.
constrain queues.
- A profile carries no scheduling-policy attributes (no priority, queue choice,
fairshare or preemption).
- Any combination of an allowed queue and an allowed profile is valid. Each is
governed by its own access rules; for profiles, that is RBAC permission.
- Any combination of an allowed queue and a profile is valid. Queues keep
their access rules; per-profile access control comes later
(`app-access-control`).
- Resource values in a profile describe what the application needs (its
essential resource requirement and per-job execution limits). They are
not scheduling policy. Queue-level scheduling limits keep applying on top,
@ -305,8 +301,8 @@ fits XCE's LSF-style job model.
that no longer satisfies its profile pends with a reason, and running jobs
are unaffected. Job details show the profile name and the effective mode.
- **The apiserver never checks node accounts** (user decision, 2026-09-29).
- Submit-time validation covers profile existence, RBAC permission, the
additive rule and paths only.
- Submit-time validation covers profile existence, the additive rule and
paths only (no per-profile permission in v1).
- The execution account is the worker's concern. If a `direct` job's execution
user doesn't exist on the node, the worker fails the job at launch with a
clear, user-visible reason, instead of today's opaque systemd failure.
@ -338,9 +334,9 @@ fits XCE's LSF-style job model.
authoritative for non-REST submit paths and for a profile removed between the
two checks. If the profile has gone by then, the job is rejected, never run
with a fallback profile.
- **The apiserver additionally enforces the RBAC permission** for the profile
(middleware chain unchanged; a `RequirePermission`-style check) and checks
the additive rule early (`preCheckJobSubmitRequest`).
- **The apiserver additionally checks the additive rule early**
(`preCheckJobSubmitRequest`); the middleware chain is unchanged. The
profile listing route uses `RequirePermission("cluster:view")`.
- **The job's own values stay in its existing fields** (`launch_type`,
pre/post exec, exdata env and limits, resreq). New fields (all additive
Cap'n Proto; WAL submit/dispatch facts and snapshot carry them with field
@ -391,7 +387,8 @@ fits XCE's LSF-style job model.
profile named `default` in the file **replaces** the built-in one, so
admins can customise the default without setting `default_application`.
- **No secrets in profiles.** Profile env values and pre/post-exec paths
are visible to every `app:view` holder (profile listing, job details);
are visible to every user who can view profiles (`cluster:view`) and in
job details;
`xceadmin` warns on env names that look like secrets (`*TOKEN*`,
`*SECRET*`, `*PASSWORD*`, `*_KEY`), as for presets.
- **No override markers.** Every profile value binds the job (additive
@ -657,7 +654,7 @@ defaults a profile does not (everything but default reservations):
into its own local file, so a server preset being removed never affects
users. `preset diff` / `pull --force` are user-initiated.
- User-to-user sharing by `preset export` / `import` (file, mail, git).
- Presets carry no privilege: `app:use`, `queue:submit`, the profile's
- Presets carry no privilege: `queue:submit` (later `app:use`), the profile's
essentials, queue ceilings and project quotas still apply at submit.
### Dispatch record
@ -759,7 +756,8 @@ with the reason "application profile X is not defined".
Decided 2026-10-12 (user), so a rename never strands jobs:
- A profile may list `aliases: [old-name, ...]`. An alias resolves to the
profile everywhere: merge, dispatch record, content hash (the target's),
RBAC (`app:use` is checked against the target profile's name).
and, once `app-access-control` lands, its permission check (against the
target profile's name).
- Jobs keep the name they recorded; the scheduler and controller resolve it
through the alias. New submits that name an alias are accepted and record
the **target's** name, so the alias can be removed once old jobs drain.
@ -788,7 +786,8 @@ Decided 2026-10-12 (user), so a rename never strands jobs:
- **Restart carries the profile name.** `POST /:jobids/restart` rebuilds the
new job field by field from the old job's record (bug-1968 shows what is
lost otherwise), so it must copy the profile name (or alias); it then
re-checks `app:use` and re-reads the profile like any new dispatch.
re-reads the profile like any new dispatch (and, once
`app-access-control` lands, re-checks `app:use`).
- **Array jobs** carry one profile name on the array's submit data; every
element uses it.
- **A name that is not defined is a configuration error, never a silent
@ -822,7 +821,6 @@ Decided 2026-10-12 (user), so a rename never strands jobs:
- The profile schema (essentials, additive rule, aliases) and
`applications.yaml`, and the default profile (`default_application`).
- Submit-time validation of the profile and the additive rule.
- RBAC permission for profile use.
- Submit surfaces: REST, `xcecli --app`, harness, libxce.
- The profile name and the job's own values persisted on the job.
- The `mode:` schema field (only `direct`), the structured resreq schema
@ -882,11 +880,13 @@ Decided 2026-10-12 (user), so a rename never strands jobs:
- Multi-node sandbox (`job-sandbox-multinode`).
- Container or vm execution itself (only room for them in the schema).
- Auth backends and JWT claims.
- Per-profile access control (`app:use` / `app:view`): deferred to
`app-access-control` (user decision, 2026-10-12).
## Boundary Candidates
- The profile model and config (schema, validation, live upgrade).
- Submit-time validation of the profile and the additive rule (controller).
- Access control (RBAC permission) and early validation (apiserver).
- Early validation (apiserver).
- Submit and listing surfaces (REST, xcecli, harness, libxce).
- Persisting the profile name and the job's own values (wire, WAL submit
fact, snapshot).
@ -906,7 +906,8 @@ Decided 2026-10-12 (user), so a rename never strands jobs:
seam).
- The config pipeline (`clusterconfig-schema-split`, `config-upgrade-snapshot`,
`admin-config-tool`).
- RBAC (`rbac_check.go`).
- RBAC (`rbac_check.go`), only for the reused `cluster:view` on the
listing route.
- The scheduler-to-controller dispatch decision (gains the profile
content hash; `scheduler-dispatch-commit`).
- The restart path (`RestartJobByID`, bug-1968).