All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 40s
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
250 lines
7.8 KiB
YAML
250 lines
7.8 KiB
YAML
version: "0.1"
|
|
description: >
|
|
Canonical Identity Model for KeyCape / NetKingdom IAM Profile.
|
|
|
|
This file is the reviewed contract for identity entities. The runtime
|
|
authority is src/internal/domain/model.go: the server reads Go structs, not
|
|
this YAML. The two are held together by an executable conformance check
|
|
(src/internal/domain/conformance_test.go, KEY-WP-0017), which fails the build
|
|
when a runtime field has no entry here or an entry here is not read by the
|
|
runtime.
|
|
|
|
So: change the Go model and this file together. A field declared here but
|
|
deliberately not implemented must carry `runtime: false`, which is how the
|
|
check tells a reserved field apart from a forgotten one.
|
|
|
|
entities:
|
|
User:
|
|
description: "A person or service account in the identity directory."
|
|
fields:
|
|
id:
|
|
type: string
|
|
required: true
|
|
description: "Stable internal identifier. Immutable after creation."
|
|
username:
|
|
type: string
|
|
required: true
|
|
description: "Unique login name. Maps to LDAP uid."
|
|
displayName:
|
|
type: string
|
|
required: true
|
|
description: "Human-readable full name. Maps to LDAP cn."
|
|
email:
|
|
type: string
|
|
required: false
|
|
format: email
|
|
description: "Primary email address. Maps to LDAP mail."
|
|
enabled:
|
|
type: boolean
|
|
required: true
|
|
description: "Whether the account is active."
|
|
tenant:
|
|
type: string
|
|
required: false
|
|
description: >
|
|
NetKingdom IAM Profile tenant claim for this user (e.g.
|
|
tenant:friendly:binky). Absent falls back to the platform tenant
|
|
rather than emitting an empty claim, since the profile requires a
|
|
tenant on every token.
|
|
groups:
|
|
type: array
|
|
items:
|
|
type: string
|
|
ref: Group.id
|
|
description: "Group memberships by group ID."
|
|
roles:
|
|
type: array
|
|
items:
|
|
type: string
|
|
ref: Role.id
|
|
description: "Role assignments by role ID."
|
|
mfaEnrollment:
|
|
type: object
|
|
ref: MFAEnrollment
|
|
nullable: true
|
|
description: "MFA enrollment record if the user has enrolled."
|
|
ldapAttributes:
|
|
type: object
|
|
additionalProperties: true
|
|
description: "Raw LDAP attributes not covered by the canonical model."
|
|
|
|
Group:
|
|
description: "A named collection of users."
|
|
fields:
|
|
id:
|
|
type: string
|
|
required: true
|
|
description: "Stable internal identifier."
|
|
name:
|
|
type: string
|
|
required: true
|
|
description: "Unique group name. Maps to LDAP cn."
|
|
description:
|
|
type: string
|
|
required: false
|
|
description: "Human-readable description."
|
|
members:
|
|
type: array
|
|
items:
|
|
type: string
|
|
ref: User.id
|
|
description: "User IDs belonging to this group."
|
|
|
|
Role:
|
|
description: "A named permission set assigned to users."
|
|
fields:
|
|
id:
|
|
type: string
|
|
required: true
|
|
description: "Stable internal identifier."
|
|
name:
|
|
type: string
|
|
required: true
|
|
description: "Unique role name."
|
|
description:
|
|
type: string
|
|
required: false
|
|
description: "Human-readable description."
|
|
|
|
Client:
|
|
description: "A registered OIDC client. Registration is static in v0.1."
|
|
fields:
|
|
clientId:
|
|
type: string
|
|
required: true
|
|
description: "OAuth2 client_id."
|
|
displayName:
|
|
type: string
|
|
required: true
|
|
description: "Human-readable client name."
|
|
redirectUris:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uri
|
|
required: false
|
|
minItems: 1
|
|
description: >
|
|
Allowed redirect URIs. Wildcards are NEVER permitted. Required for any
|
|
client using the authorization_code grant; a client_credentials-only
|
|
client registers none.
|
|
allowedScopes:
|
|
type: array
|
|
items:
|
|
type: string
|
|
required: true
|
|
description: "Scopes this client may request."
|
|
grantTypes:
|
|
type: array
|
|
items:
|
|
type: string
|
|
enum: [authorization_code, client_credentials]
|
|
required: true
|
|
description: >
|
|
Allowed OAuth2 grant types. An empty or absent value means
|
|
authorization_code, which is what config validation assumes.
|
|
clientType:
|
|
type: string
|
|
enum: [confidential, public]
|
|
required: true
|
|
description: "confidential = server-side app; public = SPA or native."
|
|
secretRef:
|
|
type: string
|
|
nullable: true
|
|
description: "Reference to the client secret (confidential clients only)."
|
|
audience:
|
|
type: string
|
|
nullable: true
|
|
description: >
|
|
Static resource audience for access tokens. ID tokens keep the client
|
|
audience. Absent means the access-token audience is the client ID.
|
|
serviceSubject:
|
|
type: string
|
|
nullable: true
|
|
description: >
|
|
Subject claim for client_credentials tokens (e.g. service:secrets-engine).
|
|
Required together with tenant for that grant.
|
|
tenant:
|
|
type: string
|
|
nullable: true
|
|
description: >
|
|
Tenant claim emitted for this client's service tokens. Bound at
|
|
registration and never influenced by request parameters; see
|
|
docs/tenant-claim-contract.md.
|
|
roles:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "Role claims emitted for this client's service tokens."
|
|
mfaOptional:
|
|
type: boolean
|
|
description: >
|
|
Require MFA only after factor enrollment for this browser client,
|
|
overriding the provider require-for-all default. Enrollment lookup
|
|
failures deny login. Cannot be combined with mfaRequired. Explicit
|
|
AAL2 requests still require MFA.
|
|
mfaRequired:
|
|
type: boolean
|
|
nullable: true
|
|
description: >
|
|
Per-client MFA requirement. Absent means the provider default
|
|
(mandatory MFA); false lowers ordinary login to AAL1 while acr_values
|
|
can still force step-up.
|
|
registrationUrl:
|
|
type: string
|
|
format: uri
|
|
nullable: true
|
|
description: "Registration handoff target for unknown subjects."
|
|
enrollmentUrl:
|
|
type: string
|
|
format: uri
|
|
nullable: true
|
|
description: "Factor-enrollment handoff target for unenrolled subjects."
|
|
tokenProfile:
|
|
type: string
|
|
runtime: false
|
|
description: >
|
|
Reserved. Declared for future token configuration profiles; the runtime
|
|
does not read it.
|
|
environments:
|
|
type: array
|
|
items:
|
|
type: string
|
|
runtime: false
|
|
description: >
|
|
Reserved. Environments this client is registered for (e.g. prod,
|
|
staging); the runtime does not read it.
|
|
|
|
Membership:
|
|
description: "Explicit link between a user and a group."
|
|
fields:
|
|
userId:
|
|
type: string
|
|
required: true
|
|
ref: User.id
|
|
groupId:
|
|
type: string
|
|
required: true
|
|
ref: Group.id
|
|
|
|
MFAEnrollment:
|
|
description: "Records MFA enrollment state for a user via privacyIDEA."
|
|
fields:
|
|
userId:
|
|
type: string
|
|
required: true
|
|
ref: User.id
|
|
provider:
|
|
type: string
|
|
required: true
|
|
enum: [privacyidea]
|
|
description: "MFA provider. Only privacyidea is supported in v0.1."
|
|
state:
|
|
type: string
|
|
required: true
|
|
enum: [enabled, disabled, pending]
|
|
description: "Current enrollment state."
|
|
enrolledAt:
|
|
type: string
|
|
format: datetime
|
|
description: "ISO 8601 timestamp of enrollment."
|