This commit is contained in:
+43
@@ -0,0 +1,43 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Cloud operator sessions are the only human API authentication path
|
||||
The system SHALL authorize human Cloud API operations through persistent Cloud
|
||||
user sessions and SHALL not require configured static bearer credentials for
|
||||
production startup or normal Console operation.
|
||||
|
||||
#### Scenario: Production starts without credential JSON
|
||||
- **WHEN** the Cloud API starts in production with a current database schema
|
||||
and no configured public, Host, or enrollment credential JSON
|
||||
- **THEN** the application starts, exposes health and authentication routes,
|
||||
and rejects unauthenticated protected API requests
|
||||
|
||||
#### Scenario: Signed-in operator uses a protected API route
|
||||
- **WHEN** an enabled Cloud user has a valid session and calls an operation
|
||||
allowed by the user's role scopes
|
||||
- **THEN** the operation is authorized without an Authorization bearer header
|
||||
|
||||
### Requirement: The Console contains no token or user-directory management surface
|
||||
The Console SHALL offer login, logout, current-account display, and password
|
||||
change, and SHALL not render bearer-token controls, token persistence, Users
|
||||
navigation, or user-management forms.
|
||||
|
||||
#### Scenario: Unauthenticated operator opens the Console
|
||||
- **WHEN** no valid user session exists
|
||||
- **THEN** the Console presents the username/password login flow without an API
|
||||
token alternative
|
||||
|
||||
#### Scenario: Administrator opens the Console
|
||||
- **WHEN** an administrator signs in
|
||||
- **THEN** the Console presents normal authorized operational views but no
|
||||
user-directory navigation or account lifecycle form
|
||||
|
||||
### Requirement: Account provisioning and recovery remain interactive administration operations
|
||||
The system SHALL retain interactive, non-echoed administration CLI commands to
|
||||
create, reset, enable, and revoke Cloud user accounts without accepting
|
||||
passwords through Compose configuration or command-line arguments.
|
||||
|
||||
#### Scenario: Initial administrator is created after deployment
|
||||
- **WHEN** an operator runs `device-cloud-admin users create` against the
|
||||
migrated Cloud database and completes the password prompts
|
||||
- **THEN** an enabled administrator account is created without a deployment
|
||||
token or plaintext password in process arguments
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Fresh Hosts register directly with the trusted Cloud API
|
||||
The Cloud API SHALL accept a first Host registration without a configured
|
||||
enrollment token or Authorization header, assign a durable `host_id`, and store
|
||||
only the digest of the Host-generated high-entropy secret.
|
||||
|
||||
#### Scenario: Fresh Host registers without static configuration
|
||||
- **WHEN** a Host Agent with no cached identity sends a valid instance
|
||||
identifier and generated Host secret to the enrollment endpoint
|
||||
- **THEN** the Cloud API creates or returns the durable Host identity and does
|
||||
not require a pre-shared deployment credential
|
||||
|
||||
#### Scenario: Registration is retried by the same Host
|
||||
- **WHEN** the same Host retries registration with its original instance
|
||||
identifier and candidate secret after losing the response
|
||||
- **THEN** the Cloud API returns the existing Host identity without creating a
|
||||
duplicate Host row
|
||||
|
||||
### Requirement: Registered Hosts authenticate all later operational requests
|
||||
The system SHALL require the persisted Host secret for device enrollment,
|
||||
heartbeat, claim, renewal, and result operations after first registration, and
|
||||
SHALL bind each accepted request to its registered `host_id`.
|
||||
|
||||
#### Scenario: Registered Host sends a heartbeat
|
||||
- **WHEN** a Host presents its persisted secret for its own Host identity
|
||||
- **THEN** the Cloud API accepts the heartbeat subject to normal validation
|
||||
|
||||
#### Scenario: Caller attempts a Host operation without its secret
|
||||
- **WHEN** a caller accesses any post-registration Host operation without a
|
||||
valid secret bound to the path Host identity
|
||||
- **THEN** the Cloud API rejects the operation without changing Host state
|
||||
|
||||
### Requirement: Host Agent configuration contains no static Cloud credential
|
||||
The Host Agent SHALL use its cached identity when present and otherwise perform
|
||||
direct registration, without `HOST_AGENT_HOST_ID`, `HOST_AGENT_TOKEN`, or
|
||||
`HOST_AGENT_ENROLLMENT_TOKEN` configuration.
|
||||
|
||||
#### Scenario: Fresh Host starts with only its local state path
|
||||
- **WHEN** a Host Agent starts with no cached Cloud identity and no static Host
|
||||
credential environment values
|
||||
- **THEN** it generates and persists an identity through direct registration
|
||||
before starting heartbeat or assignment polling
|
||||
@@ -0,0 +1,39 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Host identity can be established by direct registration
|
||||
The internal Host Agent API SHALL accept a fresh Host registration without a
|
||||
pre-shared deployment credential, SHALL assign a durable Host identifier, and
|
||||
SHALL store only the digest of the Host-generated secret for subsequent
|
||||
host-scoped authentication.
|
||||
|
||||
#### Scenario: Fresh Host establishes an identity
|
||||
- **WHEN** a fresh Host Agent submits a valid registration request containing
|
||||
its instance identifier and generated secret
|
||||
- **THEN** the control plane returns a durable Host identifier and stores only
|
||||
the secret digest bound to that Host
|
||||
|
||||
#### Scenario: Registration request is retried
|
||||
- **WHEN** the same Host Agent repeats registration with its original instance
|
||||
identifier and secret after a lost response
|
||||
- **THEN** the control plane returns the existing Host identifier without
|
||||
creating a second Host identity
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Host identity is authenticated and bound to one host id
|
||||
After direct registration, the internal Host Agent API SHALL require a
|
||||
host-scoped bearer principal for all Host operational requests and SHALL reject
|
||||
any request that attempts to act for a `host_id` different from the
|
||||
authenticated principal's bound host. The initial registration endpoint is the
|
||||
only exception and establishes that bound principal.
|
||||
|
||||
#### Scenario: Host authenticates as itself after registration
|
||||
- **WHEN** a Host Agent presents the persisted generated secret bound to its
|
||||
requested `host_id`
|
||||
- **THEN** the internal API authorizes permitted heartbeat, claim, renewal, and
|
||||
result operations
|
||||
|
||||
#### Scenario: Host attempts to impersonate another host
|
||||
- **WHEN** valid credentials bound to host A are used on a request for host B
|
||||
- **THEN** the internal API rejects the request without reading or modifying
|
||||
host B's state
|
||||
@@ -0,0 +1,36 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Pluggable authentication hook with a safe default
|
||||
The system SHALL evaluate every platform SDK route through a configurable
|
||||
scope-aware `AuthProvider` hook. The deployable Cloud Control Plane SHALL
|
||||
reject anonymous access outside an explicit insecure-development override, but
|
||||
production startup SHALL not require configured static bearer credentials.
|
||||
|
||||
#### Scenario: Production starts without configured bearer credentials
|
||||
- **WHEN** the Cloud Control Plane is configured as production with a usable
|
||||
database and no static bearer credential configuration
|
||||
- **THEN** startup succeeds and protected platform routes reject unauthenticated
|
||||
requests
|
||||
|
||||
#### Scenario: Explicit local anonymous override
|
||||
- **WHEN** a non-production operator explicitly enables the insecure
|
||||
anonymous-development override
|
||||
- **THEN** platform routes may use an anonymous principal and the application
|
||||
records that insecure mode is active
|
||||
|
||||
#### Scenario: Custom AuthProvider is honored
|
||||
- **WHEN** a caller configures a custom `AuthProvider` that rejects a request
|
||||
or omits its required scope
|
||||
- **THEN** the platform SDK route returns an authentication or authorization
|
||||
error without executing its handler operation
|
||||
|
||||
## REMOVED Requirements
|
||||
|
||||
### Requirement: Python SDK supports authenticated requests
|
||||
**Reason**: The deployment no longer provisions or accepts static bearer
|
||||
credentials for public platform access; human operations use Cloud user
|
||||
sessions.
|
||||
|
||||
**Migration**: Replace bearer-token SDK workflows with authenticated Console
|
||||
user-session workflows. A non-human service credential model is outside this
|
||||
change and must be designed separately before reintroducing SDK automation.
|
||||
Reference in New Issue
Block a user