docs(openspec): archive fpagent-release-installer and sync specs
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
schema: spec-driven
|
||||||
|
created: 2026-10-02
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# Design
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
See proposal.md — Why. The `fingerprint-agent` repository and its releases are
|
||||||
|
private: an unauthenticated request to the forge's releases API answers `404`.
|
||||||
|
Releases already publish, per build, a generic bundle
|
||||||
|
(`fpagent-<version>-linux-x86_64.tar.gz`), per-Ubuntu offline bundles
|
||||||
|
(`fpagent-<version>-ubuntu-<codename>-x86_64.tar.gz`) with the libfprint `.deb`
|
||||||
|
closure vendored, and a `.sha256` beside each. Every bundle already contains
|
||||||
|
the fpagent binary, the udev rule, and its own `install.sh` that handles
|
||||||
|
libfprint, udev, `plugdev` and the systemd service. The tools app is an Express
|
||||||
|
server with a hardcoded-configuration policy whose only sanctioned environment
|
||||||
|
variables were the Image Cropper credentials.
|
||||||
|
|
||||||
|
## Goals / Non-Goals
|
||||||
|
|
||||||
|
**Goals:**
|
||||||
|
|
||||||
|
- A field laptop installs or updates fpagent with one public command.
|
||||||
|
- The forge credential never reaches the field laptop.
|
||||||
|
- Reuse the bundle's installer rather than reimplementing hardware setup.
|
||||||
|
|
||||||
|
**Non-Goals:**
|
||||||
|
|
||||||
|
- Replacing the bundle installer, or the forge's own release tooling.
|
||||||
|
- Authenticating the installer: it is intentionally public.
|
||||||
|
- Supporting architectures other than x86_64 (the bundle installer already
|
||||||
|
requires it).
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
1. **Proxy the release through the app; do not embed the key in the script.**
|
||||||
|
The credential lives in `GITEA_RELEASE_INSTALL_KEY` and the app fetches the
|
||||||
|
private release server-side. The alternative — rendering the key into the
|
||||||
|
served script so the client could call the forge directly — publishes a
|
||||||
|
repository credential to every installer and any `curl`; rejected.
|
||||||
|
|
||||||
|
2. **Two thin routes, no proxy framework.** `/fpagent/releases/latest` returns
|
||||||
|
a trimmed `{tag, assets:[{name,url}]}` with same-origin URLs, and
|
||||||
|
`/fpagent/releases/download/:tag/:name` streams one asset. Both are
|
||||||
|
registered before the session middleware so they stay public and do no
|
||||||
|
per-request PocketBase work. A single combined "give me the right tarball"
|
||||||
|
route was considered but needs the server to guess the client's OS; the
|
||||||
|
client knows its own codename, so selection happens in the script.
|
||||||
|
|
||||||
|
3. **The installer delegates to the bundle's own `install.sh`.** All hardware
|
||||||
|
and dependency logic already exists and is versioned with the binary;
|
||||||
|
reimplementing it in the hosted script would duplicate it and drift. The
|
||||||
|
hosted script only fetches, verifies, extracts, and forwards flags.
|
||||||
|
|
||||||
|
4. **Bundle selection prefers the codename offline bundle.** When the host's
|
||||||
|
`/etc/os-release` `VERSION_CODENAME` matches a published offline bundle, use
|
||||||
|
it (no network needed for the dependency closure); otherwise fall back to
|
||||||
|
the generic online bundle, whose installer apt-gets libfprint.
|
||||||
|
|
||||||
|
5. **Checksum verification, not signature verification.** The release publishes
|
||||||
|
sha256 only, so the installer verifies sha256 over TLS from the same origin
|
||||||
|
it trusts for the script itself. GPG would require release signing that does
|
||||||
|
not exist yet; deferred.
|
||||||
|
|
||||||
|
6. **Asset names are validated server-side** against a conservative pattern,
|
||||||
|
so a crafted tag or name cannot walk the forge path or reach another host.
|
||||||
|
|
||||||
|
## Risks / Trade-offs
|
||||||
|
|
||||||
|
- [A compromised tools app serves a malicious installer] → the app is already
|
||||||
|
trusted to serve the tools pages and holds the operator session; the
|
||||||
|
installer is not a new trust boundary. TLS to `tools.yrka.app` is the same
|
||||||
|
trust as the app.
|
||||||
|
- [The forge changes its bundle naming] → selection falls back to the generic
|
||||||
|
bundle, and a release with no matching asset fails loudly rather than
|
||||||
|
installing something wrong.
|
||||||
|
- [The app buffers an asset in memory] → bundles are tens of MB; acceptable,
|
||||||
|
and requests are rare. Streaming can replace it if that changes.
|
||||||
|
|
||||||
|
## Migration Plan
|
||||||
|
|
||||||
|
Add `GITEA_RELEASE_INSTALL_KEY` to `.env`/`.env.production` (already supplied)
|
||||||
|
and deploy the app; the installer and proxy are new routes and change no
|
||||||
|
existing behavior. Rollback = remove the routes; nothing else depends on them.
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
|
||||||
|
None.
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Proposal: fpagent-release-installer
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
Field laptops need `fpagent` installed and kept current, but the
|
||||||
|
`fingerprint-agent` repository is private: its releases require a forge token
|
||||||
|
that operators do not have. Today an operator must obtain a bundle out of band
|
||||||
|
and run its installer by hand. A public one-line installer hosted by the tools
|
||||||
|
app removes that step while keeping the forge credential server-side.
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- Add a public installer script served at `/fpagent/install.sh`, intended to be
|
||||||
|
piped into `bash`. It fetches the latest release, selects the bundle matching
|
||||||
|
the host (the Ubuntu-codename offline bundle when present, else the generic
|
||||||
|
online bundle), verifies the published sha256, extracts it, and runs the
|
||||||
|
bundle's own installer, forwarding flags such as `--enable-service`,
|
||||||
|
`--check` and `--uninstall`.
|
||||||
|
- Add same-origin proxy routes `/fpagent/releases/latest` and
|
||||||
|
`/fpagent/releases/download/:tag/:name` that read the private release from the
|
||||||
|
forge using the `GITEA_RELEASE_INSTALL_KEY` environment variable and stream
|
||||||
|
assets to the client. The token and the forge host are never exposed.
|
||||||
|
- Extend the app's sanctioned environment configuration to include the installer
|
||||||
|
key, alongside the existing Image Cropper credentials.
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
### New Capabilities
|
||||||
|
|
||||||
|
- `fpagent-installer`: the public installer surface — the download/verify/handoff
|
||||||
|
script and the token-guarded same-origin release proxy that backs it.
|
||||||
|
|
||||||
|
### Modified Capabilities
|
||||||
|
|
||||||
|
- `tools-app`: the hardcoded-configuration requirement now sanctions a second
|
||||||
|
environment variable (the fpagent installer key) in addition to the Image
|
||||||
|
Cropper credentials.
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
- `tools/server.js`: `GITEA_URL` / `FPAGENT_REPO` constants, the installer key
|
||||||
|
read, and two public routes registered before the session middleware.
|
||||||
|
- `tools/public/fpagent/install.sh`: new installer script.
|
||||||
|
- `tools/test/fpagent-install.test.js`: proxy and script tests.
|
||||||
|
- `.env` / `.env.production` hold the key; `.env.example` and `README.md`
|
||||||
|
document the install flow.
|
||||||
|
- Depends on the private `fingerprint-agent` releases and their bundle naming
|
||||||
|
(`fpagent-<version>-{linux-x86_64|ubuntu-<codename>-x86_64}.tar.gz`) plus the
|
||||||
|
matching `.sha256` assets.
|
||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
# fpagent-installer Specification
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Lets a field laptop install the latest private `fpagent` release with a single
|
||||||
|
public command, without ever handling the forge credential — the tools app
|
||||||
|
proxies the private release and serves the installer.
|
||||||
|
|
||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Public installer endpoint
|
||||||
|
|
||||||
|
The app SHALL serve an installer script at `/fpagent/install.sh` that is
|
||||||
|
reachable without authentication. When run, the script SHALL fetch the latest
|
||||||
|
release metadata, choose a bundle for the host, verify the bundle's published
|
||||||
|
sha256 checksum, extract it, and hand off to the extracted bundle's own
|
||||||
|
installer. The script SHALL be served uncached.
|
||||||
|
|
||||||
|
#### Scenario: Installer is fetched anonymously
|
||||||
|
|
||||||
|
- **WHEN** a client requests `/fpagent/install.sh` without a session
|
||||||
|
- **THEN** the app returns the installer script and does not redirect to login
|
||||||
|
|
||||||
|
#### Scenario: Host-appropriate bundle is chosen
|
||||||
|
|
||||||
|
- **WHEN** the latest release offers both a bundle for the host's Ubuntu
|
||||||
|
codename and a generic bundle
|
||||||
|
- **THEN** the installer uses the codename bundle
|
||||||
|
|
||||||
|
#### Scenario: Generic bundle is the fallback
|
||||||
|
|
||||||
|
- **WHEN** the latest release offers no bundle matching the host's Ubuntu
|
||||||
|
codename
|
||||||
|
- **THEN** the installer uses the generic bundle
|
||||||
|
|
||||||
|
#### Scenario: Checksum is verified before extraction
|
||||||
|
|
||||||
|
- **WHEN** the installer downloads a bundle and its published checksum
|
||||||
|
- **THEN** it verifies the checksum before extracting and refuses to install
|
||||||
|
when the checksum does not match
|
||||||
|
|
||||||
|
#### Scenario: Options are forwarded to the bundled installer
|
||||||
|
|
||||||
|
- **WHEN** the installer is invoked with options such as `--enable-service` or
|
||||||
|
`--check`
|
||||||
|
- **THEN** it passes those options through to the extracted bundle's installer
|
||||||
|
|
||||||
|
#### Scenario: No compatible bundle
|
||||||
|
|
||||||
|
- **WHEN** the latest release contains no bundle for the host architecture
|
||||||
|
- **THEN** the installer exits with a failure message and installs nothing
|
||||||
|
|
||||||
|
### Requirement: Release metadata endpoint
|
||||||
|
|
||||||
|
The app SHALL expose a same-origin endpoint that returns the latest release's
|
||||||
|
tag and the names of its downloadable assets as same-origin URLs. The app SHALL
|
||||||
|
authenticate to the private forge using the configured release key, SHALL omit
|
||||||
|
asset names that are not valid asset names, and SHALL NOT reveal the release
|
||||||
|
key or the forge host to clients.
|
||||||
|
|
||||||
|
#### Scenario: Latest release is returned
|
||||||
|
|
||||||
|
- **WHEN** a client requests the latest-release endpoint and the forge returns
|
||||||
|
a release
|
||||||
|
- **THEN** the response carries the release tag and each asset's name and a
|
||||||
|
same-origin URL under `/fpagent/releases/download/`
|
||||||
|
|
||||||
|
#### Scenario: Unsafe asset names are omitted
|
||||||
|
|
||||||
|
- **WHEN** the forge release lists an asset whose name is not a valid asset
|
||||||
|
name
|
||||||
|
- **THEN** that asset does not appear in the response
|
||||||
|
|
||||||
|
#### Scenario: Release key is not exposed
|
||||||
|
|
||||||
|
- **WHEN** any client fetches the latest-release endpoint
|
||||||
|
- **THEN** the response body contains neither the release key nor the forge host
|
||||||
|
|
||||||
|
#### Scenario: Installer not configured
|
||||||
|
|
||||||
|
- **WHEN** the release key is not configured
|
||||||
|
- **THEN** the endpoint answers that the installer is not configured
|
||||||
|
|
||||||
|
#### Scenario: Forge unavailable
|
||||||
|
|
||||||
|
- **WHEN** the forge cannot be reached or returns an error for the latest
|
||||||
|
release
|
||||||
|
- **THEN** the endpoint answers with a gateway error
|
||||||
|
|
||||||
|
### Requirement: Release asset download proxy
|
||||||
|
|
||||||
|
The app SHALL stream a requested release asset to the client through a
|
||||||
|
same-origin route, authenticating the upstream request with the release key so
|
||||||
|
the client sends no credentials. It SHALL reject asset names that are not valid
|
||||||
|
asset names and SHALL report a missing asset as not found.
|
||||||
|
|
||||||
|
#### Scenario: Asset is streamed without client credentials
|
||||||
|
|
||||||
|
- **WHEN** a client requests a release asset by tag and name without any
|
||||||
|
credential
|
||||||
|
- **THEN** the app fetches it from the forge with the release key and streams
|
||||||
|
its bytes to the client
|
||||||
|
|
||||||
|
#### Scenario: Invalid asset name is rejected
|
||||||
|
|
||||||
|
- **WHEN** a client requests an asset whose tag or name is not a valid asset
|
||||||
|
name
|
||||||
|
- **THEN** the app rejects the request without contacting the forge
|
||||||
|
|
||||||
|
#### Scenario: Missing asset
|
||||||
|
|
||||||
|
- **WHEN** the forge reports the requested asset as not found
|
||||||
|
- **THEN** the app answers with not found
|
||||||
|
|
||||||
|
#### Scenario: Installer not configured
|
||||||
|
|
||||||
|
- **WHEN** the release key is not configured
|
||||||
|
- **THEN** the endpoint answers that the installer is not configured
|
||||||
|
|
||||||
|
### Requirement: Installer credential stays server-side
|
||||||
|
|
||||||
|
The app SHALL read the private-forge release key from the
|
||||||
|
`GITEA_RELEASE_INSTALL_KEY` environment variable. The key SHALL NOT appear in
|
||||||
|
the installer script, in any release metadata response, or in any streamed
|
||||||
|
asset.
|
||||||
|
|
||||||
|
#### Scenario: Served installer carries no credential
|
||||||
|
|
||||||
|
- **WHEN** a client fetches `/fpagent/install.sh`
|
||||||
|
- **THEN** the response contains no release key
|
||||||
|
|
||||||
|
#### Scenario: Credential supplied by the environment
|
||||||
|
|
||||||
|
- **WHEN** the release key is supplied in the environment
|
||||||
|
- **THEN** the installer and proxy endpoints use it without any change to the
|
||||||
|
hardcoded configuration
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# tools-app Specification
|
||||||
|
|
||||||
|
## MODIFIED Requirements
|
||||||
|
|
||||||
|
### Requirement: Configuration is hardcoded
|
||||||
|
|
||||||
|
The app SHALL hardcode all configuration in source: port `4173`, portal
|
||||||
|
`https://portal.yrka.app`, PocketBase `https://pb.itcass.net`, a2loft
|
||||||
|
`https://apis.a2loft.net`, agent `http://127.0.0.1:9000`, and the fingerprint
|
||||||
|
agent release forge `https://sources.yrka.app`. There SHALL be no runtime
|
||||||
|
configuration via environment variables or config files, with two exceptions:
|
||||||
|
the Image Cropper's service credentials (Minio keys, Azure storage connection
|
||||||
|
string, nodered credentials, cleanup-service key) SHALL come from environment
|
||||||
|
variables and SHALL NOT be stored in source; and the Fingerprint Agent
|
||||||
|
installer's release key (`GITEA_RELEASE_INSTALL_KEY`) SHALL come from the
|
||||||
|
environment and SHALL NOT be stored in source.
|
||||||
|
|
||||||
|
#### Scenario: No configuration required to run
|
||||||
|
|
||||||
|
- **WHEN** the app is started with no environment variables or config files
|
||||||
|
- **THEN** it serves on port 4173 with the hardcoded external endpoints
|
||||||
|
|
||||||
|
#### Scenario: Cropper credentials from the environment
|
||||||
|
|
||||||
|
- **WHEN** the cropper credentials are supplied as environment variables
|
||||||
|
- **THEN** the cropper routes use them without any change to the hardcoded
|
||||||
|
URL/port configuration
|
||||||
|
|
||||||
|
#### Scenario: Installer key from the environment
|
||||||
|
|
||||||
|
- **WHEN** the fpagent installer release key is supplied as an environment
|
||||||
|
variable
|
||||||
|
- **THEN** the installer and release-proxy routes use it without any change to
|
||||||
|
the hardcoded URL/port configuration
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Tasks
|
||||||
|
|
||||||
|
- [x] 1. Server: `GITEA_URL`/`FPAGENT_REPO` constants, the installer key read
|
||||||
|
from `GITEA_RELEASE_INSTALL_KEY`, and two public proxy routes registered
|
||||||
|
before the session middleware: `GET /fpagent/releases/latest` (trimmed
|
||||||
|
`{tag, assets:[{name,url}]}`, same-origin URLs, unsafe names dropped) and
|
||||||
|
`GET /fpagent/releases/download/:tag/:name` (validated names, streamed with
|
||||||
|
the key, 404/502 mapping, 503 when unconfigured).
|
||||||
|
- [x] 2. Installer script `tools/public/fpagent/install.sh`: fetch metadata,
|
||||||
|
prefer the host-codename offline bundle over the generic one, download and
|
||||||
|
verify sha256, extract, and forward all options to the bundle's `install.sh`.
|
||||||
|
Served uncached at `/fpagent/install.sh`.
|
||||||
|
- [x] 3. Tests (`tools/test/fpagent-install.test.js`): latest proxy shape and
|
||||||
|
token non-disclosure, asset streaming with upstream auth, invalid-name
|
||||||
|
rejection, missing-asset 404, unconfigured 503, public script serving, and
|
||||||
|
`bash -n` on the script.
|
||||||
|
- [x] 4. Docs/config: `GITEA_RELEASE_INSTALL_KEY` in `.env.example`, installer
|
||||||
|
and configuration notes in `README.md`.
|
||||||
|
- [x] 5. Verified: 55 tests pass (48 existing + 7 new); routes exercised live
|
||||||
|
against the forge (latest release `v1.0.0`, proxied checksum matches the
|
||||||
|
publisher's, invalid name refused); the installer run end to end against a
|
||||||
|
fake release base — codename bundle chosen, checksum pass and fail, options
|
||||||
|
forwarded to the extracted bundle installer.
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
# fpagent-installer Specification
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Lets a field laptop install the latest private `fpagent` release with a single
|
||||||
|
public command, without ever handling the forge credential — the tools app
|
||||||
|
proxies the private release and serves the installer.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Public installer endpoint
|
||||||
|
|
||||||
|
The app SHALL serve an installer script at `/fpagent/install.sh` that is
|
||||||
|
reachable without authentication. When run, the script SHALL fetch the latest
|
||||||
|
release metadata, choose a bundle for the host, verify the bundle's published
|
||||||
|
sha256 checksum, extract it, and hand off to the extracted bundle's own
|
||||||
|
installer. The script SHALL be served uncached.
|
||||||
|
|
||||||
|
#### Scenario: Installer is fetched anonymously
|
||||||
|
|
||||||
|
- **WHEN** a client requests `/fpagent/install.sh` without a session
|
||||||
|
- **THEN** the app returns the installer script and does not redirect to login
|
||||||
|
|
||||||
|
#### Scenario: Host-appropriate bundle is chosen
|
||||||
|
|
||||||
|
- **WHEN** the latest release offers both a bundle for the host's Ubuntu
|
||||||
|
codename and a generic bundle
|
||||||
|
- **THEN** the installer uses the codename bundle
|
||||||
|
|
||||||
|
#### Scenario: Generic bundle is the fallback
|
||||||
|
|
||||||
|
- **WHEN** the latest release offers no bundle matching the host's Ubuntu
|
||||||
|
codename
|
||||||
|
- **THEN** the installer uses the generic bundle
|
||||||
|
|
||||||
|
#### Scenario: Checksum is verified before extraction
|
||||||
|
|
||||||
|
- **WHEN** the installer downloads a bundle and its published checksum
|
||||||
|
- **THEN** it verifies the checksum before extracting and refuses to install
|
||||||
|
when the checksum does not match
|
||||||
|
|
||||||
|
#### Scenario: Options are forwarded to the bundled installer
|
||||||
|
|
||||||
|
- **WHEN** the installer is invoked with options such as `--enable-service` or
|
||||||
|
`--check`
|
||||||
|
- **THEN** it passes those options through to the extracted bundle's installer
|
||||||
|
|
||||||
|
#### Scenario: No compatible bundle
|
||||||
|
|
||||||
|
- **WHEN** the latest release contains no bundle for the host architecture
|
||||||
|
- **THEN** the installer exits with a failure message and installs nothing
|
||||||
|
|
||||||
|
### Requirement: Release metadata endpoint
|
||||||
|
|
||||||
|
The app SHALL expose a same-origin endpoint that returns the latest release's
|
||||||
|
tag and the names of its downloadable assets as same-origin URLs. The app SHALL
|
||||||
|
authenticate to the private forge using the configured release key, SHALL omit
|
||||||
|
asset names that are not valid asset names, and SHALL NOT reveal the release
|
||||||
|
key or the forge host to clients.
|
||||||
|
|
||||||
|
#### Scenario: Latest release is returned
|
||||||
|
|
||||||
|
- **WHEN** a client requests the latest-release endpoint and the forge returns
|
||||||
|
a release
|
||||||
|
- **THEN** the response carries the release tag and each asset's name and a
|
||||||
|
same-origin URL under `/fpagent/releases/download/`
|
||||||
|
|
||||||
|
#### Scenario: Unsafe asset names are omitted
|
||||||
|
|
||||||
|
- **WHEN** the forge release lists an asset whose name is not a valid asset
|
||||||
|
name
|
||||||
|
- **THEN** that asset does not appear in the response
|
||||||
|
|
||||||
|
#### Scenario: Release key is not exposed
|
||||||
|
|
||||||
|
- **WHEN** any client fetches the latest-release endpoint
|
||||||
|
- **THEN** the response body contains neither the release key nor the forge host
|
||||||
|
|
||||||
|
#### Scenario: Installer not configured
|
||||||
|
|
||||||
|
- **WHEN** the release key is not configured
|
||||||
|
- **THEN** the endpoint answers that the installer is not configured
|
||||||
|
|
||||||
|
#### Scenario: Forge unavailable
|
||||||
|
|
||||||
|
- **WHEN** the forge cannot be reached or returns an error for the latest
|
||||||
|
release
|
||||||
|
- **THEN** the endpoint answers with a gateway error
|
||||||
|
|
||||||
|
### Requirement: Release asset download proxy
|
||||||
|
|
||||||
|
The app SHALL stream a requested release asset to the client through a
|
||||||
|
same-origin route, authenticating the upstream request with the release key so
|
||||||
|
the client sends no credentials. It SHALL reject asset names that are not valid
|
||||||
|
asset names and SHALL report a missing asset as not found.
|
||||||
|
|
||||||
|
#### Scenario: Asset is streamed without client credentials
|
||||||
|
|
||||||
|
- **WHEN** a client requests a release asset by tag and name without any
|
||||||
|
credential
|
||||||
|
- **THEN** the app fetches it from the forge with the release key and streams
|
||||||
|
its bytes to the client
|
||||||
|
|
||||||
|
#### Scenario: Invalid asset name is rejected
|
||||||
|
|
||||||
|
- **WHEN** a client requests an asset whose tag or name is not a valid asset
|
||||||
|
name
|
||||||
|
- **THEN** the app rejects the request without contacting the forge
|
||||||
|
|
||||||
|
#### Scenario: Missing asset
|
||||||
|
|
||||||
|
- **WHEN** the forge reports the requested asset as not found
|
||||||
|
- **THEN** the app answers with not found
|
||||||
|
|
||||||
|
#### Scenario: Installer not configured
|
||||||
|
|
||||||
|
- **WHEN** the release key is not configured
|
||||||
|
- **THEN** the endpoint answers that the installer is not configured
|
||||||
|
|
||||||
|
### Requirement: Installer credential stays server-side
|
||||||
|
|
||||||
|
The app SHALL read the private-forge release key from the
|
||||||
|
`GITEA_RELEASE_INSTALL_KEY` environment variable. The key SHALL NOT appear in
|
||||||
|
the installer script, in any release metadata response, or in any streamed
|
||||||
|
asset.
|
||||||
|
|
||||||
|
#### Scenario: Served installer carries no credential
|
||||||
|
|
||||||
|
- **WHEN** a client fetches `/fpagent/install.sh`
|
||||||
|
- **THEN** the response contains no release key
|
||||||
|
|
||||||
|
#### Scenario: Credential supplied by the environment
|
||||||
|
|
||||||
|
- **WHEN** the release key is supplied in the environment
|
||||||
|
- **THEN** the installer and proxy endpoints use it without any change to the
|
||||||
|
hardcoded configuration
|
||||||
@@ -119,11 +119,14 @@ session; the OTP SHALL NOT be accepted without one.
|
|||||||
### Requirement: Configuration is hardcoded
|
### Requirement: Configuration is hardcoded
|
||||||
The app SHALL hardcode all configuration in source: port `4173`, portal
|
The app SHALL hardcode all configuration in source: port `4173`, portal
|
||||||
`https://portal.yrka.app`, PocketBase `https://pb.itcass.net`, a2loft
|
`https://portal.yrka.app`, PocketBase `https://pb.itcass.net`, a2loft
|
||||||
`https://apis.a2loft.net`, and agent `http://127.0.0.1:9000`. There SHALL be
|
`https://apis.a2loft.net`, agent `http://127.0.0.1:9000`, and the fingerprint
|
||||||
no runtime configuration via environment variables or config files, with one
|
agent release forge `https://sources.yrka.app`. There SHALL be no runtime
|
||||||
exception: the Image Cropper's service credentials (Minio keys, Azure storage
|
configuration via environment variables or config files, with two exceptions:
|
||||||
connection string, nodered credentials, cleanup-service key) SHALL come from
|
the Image Cropper's service credentials (Minio keys, Azure storage connection
|
||||||
environment variables and SHALL NOT be stored in source.
|
string, nodered credentials, cleanup-service key) SHALL come from environment
|
||||||
|
variables and SHALL NOT be stored in source; and the Fingerprint Agent
|
||||||
|
installer's release key (`GITEA_RELEASE_INSTALL_KEY`) SHALL come from the
|
||||||
|
environment and SHALL NOT be stored in source.
|
||||||
|
|
||||||
#### Scenario: No configuration required to run
|
#### Scenario: No configuration required to run
|
||||||
- **WHEN** the app is started with no environment variables or config files
|
- **WHEN** the app is started with no environment variables or config files
|
||||||
@@ -134,6 +137,12 @@ environment variables and SHALL NOT be stored in source.
|
|||||||
- **THEN** the cropper routes use them without any change to the hardcoded
|
- **THEN** the cropper routes use them without any change to the hardcoded
|
||||||
URL/port configuration
|
URL/port configuration
|
||||||
|
|
||||||
|
#### Scenario: Installer key from the environment
|
||||||
|
- **WHEN** the fpagent installer release key is supplied as an environment
|
||||||
|
variable
|
||||||
|
- **THEN** the installer and release-proxy routes use it without any change to
|
||||||
|
the hardcoded URL/port configuration
|
||||||
|
|
||||||
### Requirement: Carbon Design System UI
|
### Requirement: Carbon Design System UI
|
||||||
The tools pages SHALL be built on the Carbon Design System: Carbon web
|
The tools pages SHALL be built on the Carbon Design System: Carbon web
|
||||||
components (version-pinned via CDN) for buttons, notifications, toasts, tags,
|
components (version-pinned via CDN) for buttons, notifications, toasts, tags,
|
||||||
|
|||||||
Reference in New Issue
Block a user