Secure Send shipped on 21 August and nothing outside the code caught up. The roadmap still listed it under Deferred as "tabled", and gave as the reason that the tools plugin is browser-only by design with get_blueprint and get_models both empty - which stopped being true in the same day's commits that gave it a blueprint, a table, a migration chain, a permission and a setting. A reader following the roadmap would have concluded the feature does not exist. The generated API docs were fine: api-inventory.json and openapi.json both carry /api/tools/secrets, so the contract gates did their job. What was missing was every word written for a person, and that is the half where the security properties live. docs/SECURE-SEND.md is the new page. The parts worth having in prose rather than inferring from the code: that a lost secret is lost to everybody including an administrator, which is the same property as "a compromised database yields nothing" seen from the other side; that the 4096-character limit is the entire server-side enforcement, because a server that cannot read what it holds cannot have an opinion about content, so raising it turns a password tool into an unaudited file transfer; that redeeming is a POST because preview prefetch in chat and mail clients would otherwise spend a one-view secret before the recipient ever sees it; and that somebody should send a link to themselves through their own mail or chat client and confirm the key survives after the # before a real credential goes through it, because a product that rewrites links can strip the fragment and nothing on this side can help. securesend_allow_guests was in the database, on a settings page, and in no document. It is now in CONFIG.md with what it actually does - an unauthenticated write endpoint, rate limited per address, failing closed - rather than only its one-line description. Also corrected along the way: site_base_url was documented as scheme + host while the code deliberately tolerates a subpath in it, and the bundled plugin table in PLUGINS.md had no row for tools at all. Still missing after this: PLUGINS.md has no row for backups either.
377 lines
23 KiB
Markdown
377 lines
23 KiB
Markdown
# Configuration Reference
|
|
|
|
shopdb-flask reads configuration from two places, and the split is deliberate:
|
|
|
|
- **Environment variables** (`.env` / container env) hold **secrets and
|
|
deploy-time wiring**: database credentials, signing keys, CORS origins, ports,
|
|
API keys. These are read once at boot by `shopdb/config.py`. Never put a
|
|
secret in the Settings table.
|
|
- **The Settings table** (seeded by `flask seed settings`, edited in the UI
|
|
under Settings or the setup wizard) holds **site preferences**: branding,
|
|
ServiceNow links, floor-map images, search toggles, facility identity. These
|
|
can change at runtime without a restart and are per-instance.
|
|
|
|
Rule of thumb: if leaking it would be a security incident, it is an environment
|
|
variable. If it is a site preference an admin should be able to change in the
|
|
UI, it is a Setting.
|
|
|
|
---
|
|
|
|
## Part 1: Environment variables
|
|
|
|
Defined in `shopdb/config.py`. Copy `.env.example` to `.env` and fill in
|
|
values. In `production` (`FLASK_ENV=production`), `ProductionConfig.validate()`
|
|
refuses to boot if `SECRET_KEY`, `JWT_SECRET_KEY`, `DATABASE_URL`, or
|
|
`CORS_ORIGINS` are missing or set to the dev defaults.
|
|
|
|
### Flask core
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `FLASK_APP` | No | `wsgi.py` | Entry point for the `flask` CLI. |
|
|
| `FLASK_ENV` | Yes | `development` | `production` for live sites (triggers `validate()`). Other values: `development`, `testing`. |
|
|
| `SECRET_KEY` | Yes (prod) | dev default | Flask session/signing key. Generate: `python -c "import secrets; print(secrets.token_urlsafe(64))"`. |
|
|
| `JWT_SECRET_KEY` | Yes (prod) | dev default | JWT signing key. Different value from `SECRET_KEY`. |
|
|
| `JWT_ACCESS_TOKEN_EXPIRES` | No | `3600` | Access-token TTL in seconds. |
|
|
| `JWT_REFRESH_TOKEN_EXPIRES` | No | `2592000` | Refresh-token TTL in seconds (30 days). |
|
|
| `CORS_ORIGINS` | Yes (prod) | `http://localhost:5173` | Comma-separated explicit origins. Wildcard `*` is rejected in production. |
|
|
| `LOG_LEVEL` | No | `INFO` | Logging verbosity. |
|
|
|
|
### Database
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `DATABASE_URL` | Yes (prod) | dev localhost URL | `mysql+pymysql://<user>:<pass>@<host>:<port>/<db>?charset=utf8mb4`. Keep `?charset=utf8mb4`. |
|
|
|
|
### Authentication rate limiting
|
|
|
|
IP-based fixed-window limit on the login endpoint, defense-in-depth atop the
|
|
per-account lockout. Uses the existing cache extension (per-process, so the
|
|
limit is approximate across multiple gunicorn workers).
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `AUTH_RATELIMIT_ENABLED` | No | `True` | Set `False` to disable (TestingConfig disables it). |
|
|
| `AUTH_RATELIMIT_MAX` | No | `30` | Max login attempts per source IP per window before 429. |
|
|
| `AUTH_RATELIMIT_WINDOW_SECONDS` | No | `300` | Window length in seconds. |
|
|
|
|
### Collector ingest (ADR-006)
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `COLLECTOR_API_KEY` | No | (empty) | Shared key for `/api/collector/*`. Endpoint fails closed (denies) when unset and no managed token is presented. Sent as the `X-API-Key` header. |
|
|
| `COLLECTOR_API_KEY_<PLUGIN>` | No | (empty) | Per-plugin override, e.g. `COLLECTOR_API_KEY_COMPUTERS`. Checked before the shared key. |
|
|
|
|
The collector endpoints ALSO accept a managed API token (PAT) scoped to the
|
|
`collector.ingest` permission, sent in `X-API-Key` or as an
|
|
`Authorization: Bearer` token. Env keys stay supported as a bootstrap/legacy
|
|
fallback; a managed token is preferred because it is minted, rotated, and
|
|
revoked from Settings > API Tokens with `lastusedat` visibility. A
|
|
collector-scoped token is contained to the collector API and nothing else. See
|
|
`docs/COLLECTOR-INTEGRATION.md` (Managed collector tokens).
|
|
|
|
### Zabbix (printer supply monitoring)
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `ZABBIX_ENABLED` | No | `false` | Enable the Zabbix integration. |
|
|
| `ZABBIX_URL` | No | (empty) | Zabbix API URL. |
|
|
| `ZABBIX_TOKEN` | No | (empty) | Zabbix API bearer token. |
|
|
|
|
Note: Zabbix can also be configured via the Settings table (`zabbix_enabled`,
|
|
`zabbix_url`, `zabbix_token`). The environment values are the boot-time wiring;
|
|
prefer the Settings entries for runtime changes.
|
|
|
|
### Employee directory database (optional, read-only)
|
|
|
|
Separate HR/employee lookup DB consumed by the notifications plugin and the
|
|
public kiosks. There is no safe default for the password; an unset password
|
|
fails loud rather than trying a guessed credential.
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `EMPLOYEE_DB_HOST` | No | `localhost` | HR DB host. |
|
|
| `EMPLOYEE_DB_USER` | No | (empty) | HR DB user. |
|
|
| `EMPLOYEE_DB_PASSWORD` | No | (empty) | HR DB password. No safe default. |
|
|
| `EMPLOYEE_DB_NAME` | No | `wjf_employees` | HR DB name. |
|
|
|
|
Only used when `employee_directory_mode` (Setting) is `external`.
|
|
|
|
### CMMC USB database (optional, read-write)
|
|
|
|
Separate MySQL DB used by the USB plugin for check-in/out, lockers, and the log.
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `CMMC_USB_DB_HOST` | No | `localhost` | USB DB host. |
|
|
| `CMMC_USB_DB_USER` | No | (empty) | USB DB user. |
|
|
| `CMMC_USB_DB_PASSWORD` | No | (empty) | USB DB password. No safe default. |
|
|
| `CMMC_USB_DB_NAME` | No | `cmmc_usb` | USB DB name. |
|
|
|
|
Only used when `usb_directory_mode` (Setting) is `external`.
|
|
|
|
### docker-compose only
|
|
|
|
Read by `docker-compose.yml`, not by the Flask app directly.
|
|
|
|
| Variable | Required | Default | Notes |
|
|
|----------|----------|---------|-------|
|
|
| `MYSQL_ROOT_PASSWORD` | Yes | (none) | Root password for the bundled MySQL container. |
|
|
| `MYSQL_PASSWORD` | Yes | (none) | App-user password; must match the `DATABASE_URL` password. |
|
|
| `MYSQL_PORT` | No | `3306` | Host port for MySQL. Bound to `127.0.0.1` only. |
|
|
| `API_PORT` | No | `5001` | Host port for the API container. |
|
|
|
|
---
|
|
|
|
## Part 2: Settings table keys
|
|
|
|
Seeded by `flask seed settings` (idempotent; re-running adds anything missing).
|
|
Edited in the UI under Settings, or captured in the first-run setup wizard.
|
|
Values are stored as strings and typed by `valuetype`. Secrets in this table
|
|
(anything whose key contains `password`, `token`, or `secret`) are masked when
|
|
read back through the API.
|
|
|
|
### site
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `setup_complete` | `false` | Set true once the first-run wizard finishes; gates the `/setup` route. |
|
|
| `employee_directory_mode` | `selfhosted` | `selfhosted` (tables in this app) or `external` (a separate HR database, see `EMPLOYEE_DB_*`). |
|
|
| `usb_directory_mode` | `selfhosted` | `selfhosted` or `external` (a separate `cmmc_usb` database, see `CMMC_USB_DB_*`). |
|
|
| `site_base_url` | (empty) | Public base URL for QR codes and absolute links. Scheme + host, optionally including the subpath a site is served under (`https://host/shopdb`). Blank = use the browsing origin. |
|
|
| `facility_name` | (empty) | Facility name in the dashboard header. Blank = frontend falls back to `ShopDB`. |
|
|
| `pc_access_domain` | `device.geaerospace.net` | Domain appended to a PC hostname for remote-access links. Blank = hostname as-is. |
|
|
| `employeeid_pattern` | `^\d{9}$` | Regex a search term must match to be treated as an employee id. Invalid regex falls back to the default and never 500s. |
|
|
| `printer_hostname_template` | `Printer-{ip}.printer.geaerospace.net` | Printer hostname template. `{ip}` is the dash-separated IP address. |
|
|
| `contact_email_domain` | `geaerospace.com` | Email domain appended to a support contact's SSO to build email (`sso@domain`) and Teams-chat links. Blank hides the contact action buttons. |
|
|
| `dualpath_single_machine` | `true` | Treat a Dualpath pair (a dual-bay machine with one controller) as a single machine in the machines list, dashboard/report counts, and the floor map (the secondary bay is hidden). The data model always keeps both bay records; detail pages stay per-bay with a sibling banner. `false` lists and counts both bays separately. |
|
|
| `site_timezone` | `America/New_York` | IANA timezone for the site. Notification start/end times are entered and displayed in this zone (not the viewer's browser zone), and daily-reset notification expiry (`expirymode=dailytime`) is computed here. Editable in Settings > Site > Localization. Public-readable so kiosks/clients can resolve it. |
|
|
|
|
Notification times are stored and served in UTC; the frontend converts to
|
|
`site_timezone` via `frontend/src/utils/datetime.js` (Intl-based, DST-safe).
|
|
|
|
Change note: notification times are now timezone-correct (stored UTC, shown in
|
|
`site_timezone`); this fixes the prior offset bug where a 2:34 PM entry displayed
|
|
as 6:34 PM.
|
|
|
|
### branding
|
|
|
|
Blank values fall back to the shipped GE default asset so an un-reconfigured
|
|
install still renders. Upload replacements at Settings > Branding, which saves
|
|
them under `instance/branding/`.
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `site_logo` | `/ge-aerospace-logo.svg` | Header and login-page logo. |
|
|
| `qr_logo` | `/ge-monogram.svg` | Logo composited in printer QR labels. Blank = no overlay. |
|
|
| `badge_logo` | `/ge-aerospace-logo.svg` | Logo on the machine badge print page. |
|
|
| `site_favicon` | (empty) | Browser tab favicon. Blank = shipped `/favicon.svg`. |
|
|
| `brand_primary_color` | (empty) | Primary brand color as a CSS color value (maps to `--primary`). Blank = built-in theme color. |
|
|
| `brand_primary_dark_color` | (empty) | Primary hover/active color (maps to `--primary-dark`). Blank = auto-derived by darkening the primary color ~15%. |
|
|
| `brand_accent_color` | (empty) | Accent color for secondary buttons and badges (maps to `--secondary`). Blank = built-in theme color. |
|
|
| `brand_sidebar_color` | (empty) | Sidebar background color (maps to `--sidebar-bg`). Blank = built-in theme color. |
|
|
|
|
### printing
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `qr_target_printer` | (empty) | Custom URL template for printer QR labels. Blank = link to the printer page on this instance. Placeholders: `{printerid}`, `{assetid}`, `{assetnumber}`, `{serialnumber}`, `{ip}`, `{hostname}`. |
|
|
| `qr_target_usb` | (empty) | Custom URL template for USB label QR codes. Blank = link to the USB device page. Placeholders: `{id}`, `{serialnumber}`, `{alias}`. |
|
|
| `usb_label_style` | `barcode` | USB mini-label code style: `barcode` (CODE128 of the serial) or `qr` (QR code linking to the USB QR target). |
|
|
| `qr_target_machine` | (empty) | Custom URL template for machine labels. Blank = link to the machine page. Placeholders: `{assetid}`, `{assetnumber}`, `{serialnumber}`, `{name}`, `{pluginid}`. |
|
|
| `qr_target_computer` | (empty) | Custom URL template for computer labels. Blank = link to the computer page. Placeholders: `{assetid}`, `{assetnumber}`, `{serialnumber}`, `{name}`, `{pluginid}`. |
|
|
| `qr_target_network_device` | (empty) | Custom URL template for network-device labels. Blank = link to the device page. Placeholders: `{assetid}`, `{assetnumber}`, `{serialnumber}`, `{name}`, `{pluginid}`. |
|
|
| `qr_target_measuring_tool` | (empty) | Custom URL template for measuring-tool labels. Blank = link to the tool page. Placeholders: `{assetid}`, `{assetnumber}`, `{serialnumber}`, `{name}`, `{pluginid}`, `{locationcode}`, `{locationname}`. |
|
|
| `label_default_style` | `card` | Default asset-label layout used when a label first opens: `card` (badge with image and identity) or `plain` (just the code and a caption). |
|
|
| `label_default_codetype` | `qr` | Default asset-label code type used when a label first opens: `qr` (QR code) or `barcode` (CODE128). |
|
|
| `label_default_encodes_machine` | `assetnumber` | What a machine label encodes by default. |
|
|
| `label_default_encodes_computer` | `assetpage` | What a computer label encodes by default. |
|
|
| `label_default_encodes_printer` | `assetpage` | What a printer label encodes by default. |
|
|
| `label_default_encodes_network_device` | `assetpage` | What a network-device label encodes by default. |
|
|
| `label_default_encodes_measuring_tool` | `location` | What a measuring-tool label encodes by default. Values across these five: `assetpage`, `assetnumber`, `serialnumber`, `location` (measuring tools only), or `custom`. Overridable on the label page. |
|
|
|
|
The shared asset-label generator lives at `/print/asset-label/<assettype>/<id>` (public, like the other `/print/*` pages; `assettype` is one of `machine`, `computer`, `printer`, `network_device`, `measuring_tool`, and `id` is the asset's plugin id). It can encode the asset page link, the asset number, the serial number, a custom `qr_target_<type>` template, or - for measuring tools by default - the asset's inspection location code (the leading token of the location name, e.g. `0615`). A measuring tool with no location falls back to its asset page.
|
|
|
|
The batch generator at `/print/asset-label-batch/<assettype>` (reached from the "Print Labels" button on each asset list page) lays a multi-selection of one type onto ULINE label sheets: a 6-up 3 in x 3 in format or a dense 72-up mini-label format, with a start-cell offset for reusing partial sheets. It reuses the same code-type and `label_default_encodes_<type>` defaults as the single label.
|
|
|
|
### map
|
|
|
|
**SUPERSEDED as of 0.11.0.** A blueprint and its pixel dimensions are properties
|
|
of a LEVEL now, not of the site (ADR-017), because a site can have more than one
|
|
building and a building more than one floor. Manage them in
|
|
**Settings > Buildings and levels**, or through `/api/maplevels`.
|
|
|
|
These four keys are still present so that downgrading finds the blueprint it had,
|
|
and the levels migration copied their values onto the first level. Editing them
|
|
changes nothing on the map.
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `map_blueprint_light` | `/static/images/floorplan-placeholder.svg` | Superseded by `maplevels.blueprintlight`. Retained for downgrade only. |
|
|
| `map_blueprint_dark` | `/static/images/floorplan-placeholder.svg` | Superseded by `maplevels.blueprintdark`. |
|
|
| `map_width` | `3300` | Superseded by `maplevels.mapwidth`. |
|
|
| `map_height` | `2550` | Superseded by `maplevels.mapheight`. |
|
|
|
|
### integrations
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `servicenow_enabled` | `true` | Enable ServiceNow ticket recognition and links. Disabled = tickets render as plain text. |
|
|
| `servicenow_search_url` | geaerospaceqa.service-now.com global-search template | `{ticket}` is substituted. |
|
|
| `servicenow_ticket_prefixes` | `GEINC,GECHG,GERIT,GESCT` | Comma-separated prefixes recognized as ServiceNow tickets. |
|
|
| `servicenow_incident_url` | geaerospaceqa.service-now.com global-search template | `{ticket}` is substituted. Replace with a direct incident URL if your instance has one. |
|
|
| `servicenow_change_url` | geaerospaceqa.service-now.com global-search template | `{ticket}` is substituted. Replace with a direct change URL if your instance has one. |
|
|
| `zabbix_enabled` | `false` | Enable Zabbix for printer supply monitoring. |
|
|
| `zabbix_url` | (empty) | Zabbix API URL. |
|
|
| `zabbix_token` | (empty) | Zabbix API token (masked). |
|
|
| `warranty_dell_enabled` | `false` | Enable Dell warranty (service-tag) lookups. |
|
|
| `warranty_dell_clientid` | (empty) | Dell TechDirect API client id. |
|
|
| `warranty_dell_clientsecret` | (empty) | Dell TechDirect API client secret (masked). |
|
|
| `warranty_dell_tokenurl` | (empty) | Dell OAuth token URL. Blank = Dell default. |
|
|
| `warranty_dell_apiurl` | (empty) | Dell warranty API URL. Blank = Dell default. |
|
|
|
|
### email
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `smtp_enabled` | `false` | Enable email notifications and alerts. |
|
|
| `smtp_host` | (empty) | SMTP server hostname. |
|
|
| `smtp_port` | `587` | SMTP port (587 TLS, 465 SSL, 25 plain). |
|
|
| `smtp_username` | (empty) | SMTP auth username. |
|
|
| `smtp_password` | (empty) | SMTP auth password (masked). |
|
|
| `smtp_use_tls` | `true` | Use TLS for the SMTP connection. |
|
|
| `smtp_from_address` | (empty) | From address for outgoing email. |
|
|
| `smtp_from_name` | `ShopDB` | From name for outgoing email. |
|
|
| `alert_recipients` | (empty) | Default alert/report recipients (comma-separated). |
|
|
|
|
#### Email flows and delivery model
|
|
|
|
The mail service (`shopdb/utils/mailer.py`, stdlib `smtplib`/`ssl`/`email`
|
|
only) reads the keys above settings-first via the cached settings map, with an
|
|
environment-variable fallback (`SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`,
|
|
`SMTP_PASSWORD`, `SMTP_USE_TLS`, `SMTP_FROM_ADDRESS`, `SMTP_FROM_NAME`,
|
|
`SMTP_ALERT_RECIPIENTS`, `SMTP_ENABLED`) applied only when any `SMTP_*` env var
|
|
is present. When `smtp_enabled` is false or `smtp_host` is blank, every send is
|
|
a graceful no-op that logs a warning and returns without error, so an
|
|
unconfigured site never crashes. The SMTP password is never logged.
|
|
|
|
Three flows use it:
|
|
|
|
- Welcome email. When an admin creates a user (POST `/api/users`), the account
|
|
is flagged `mustchangepassword` and a best-effort welcome email is sent with
|
|
the facility name (`facility_name`), the username, the temporary password,
|
|
and the sign-in link (`site_base_url` + `/login`). Mail is best-effort: the
|
|
user is created even if the send fails (the response carries a `warning`). On
|
|
first login the API returns `mustchangepassword: true`; the frontend forces
|
|
the user through `/change-password` (POST `/api/auth/change-password`) before
|
|
the app. Changing the password clears the flag and resets lockout counters.
|
|
Set `sendwelcome: false` or `mustchangepassword: false` in the create body to
|
|
opt out.
|
|
|
|
- Test email. POST `/api/settings/test-email` (settings.edit) sends a probe to
|
|
the supplied `to` (or `alert_recipients`). The Email / SMTP settings page
|
|
"Send Test Email" button calls it and shows the result; a real SMTP error is
|
|
surfaced with the password scrubbed out.
|
|
|
|
- Alerts and report delivery (on-demand). POST `/api/reports/email`
|
|
(reports.export) takes `{subject, columns, rows, intro?, to?}` and mails the
|
|
rows as an HTML table. Recipients default to `alert_recipients` when `to` is
|
|
omitted, so the same endpoint serves both report delivery and alerts. Report
|
|
pages (Warranty, Toner) carry an "Email report" button that posts the rows
|
|
they already loaded.
|
|
|
|
There is NO scheduler in this app: sending is on-demand. To automate a
|
|
recurring send (e.g. a nightly warranty digest), point an external cron job
|
|
at `/api/reports/email` using an API token (PAT) scoped to `reports.export`.
|
|
See `docs/IMPORT-API.md` for the token model.
|
|
|
|
### audit
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `audit_retention_days` | `90` | Days to retain audit logs (0 = keep forever). |
|
|
|
|
### auth
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `saml_enabled` | `false` | Enable SAML SSO. |
|
|
| `saml_idp_metadata_url` | (empty) | SAML IdP metadata URL. |
|
|
| `saml_entity_id` | (empty) | SAML SP entity id. |
|
|
| `saml_acs_url` | (empty) | SAML Assertion Consumer Service URL. |
|
|
| `saml_allow_local_login` | `true` | Allow local username/password login when SAML is on. |
|
|
| `saml_auto_create_users` | `true` | Auto-create users on first SAML login. |
|
|
| `saml_admin_group` | (empty) | SAML group name that grants the admin role. |
|
|
|
|
**Personal API tokens.** Besides login JWTs and SAML, a user may create
|
|
personal API tokens (PATs) for scripts and integrations, from Settings > API
|
|
Tokens (or `POST /api/apitokens`). A PAT is sent like a JWT
|
|
(`Authorization: Bearer shopdb_pat_...`), authenticates as its owning user
|
|
across the whole API, and does not carry the hourly `JWT_ACCESS_TOKEN_EXPIRES`
|
|
limit (it never expires unless an explicit expiry is set). Only the sha256 hash
|
|
is stored; the secret is shown once at creation. This is the recommended
|
|
credential for long-running imports (see `docs/IMPORT-API.md`). There is no env
|
|
var to configure; PATs are managed entirely through the API/UI.
|
|
|
|
Creating or managing a PAT requires the `apitokens.create` permission (admins
|
|
hold it by default; grant it to other roles from Settings > Users & Roles). By
|
|
default a PAT is unscoped and acts with the full authority of its owner. A PAT
|
|
may optionally carry a scopes list (a subset of the owner's permissions, capped
|
|
at what the owner actually holds): a scoped token grants ONLY those permissions,
|
|
intersected with the owner's live permissions at use time, and suspends the
|
|
admin bypass, so it is denied on role-gated (admin-only) endpoints and on import
|
|
mode. Use an unscoped token for admin-only work and imports.
|
|
|
|
### tools
|
|
|
|
| Key | Default | Notes |
|
|
|-----|---------|-------|
|
|
| `securesend_allow_guests` | `false` | Let people with no account create Secure Send links. Public (readable before login) so the create page can show a guest the form instead of a sign-in wall. Off by default: a guest secret has no creator, so the audit trail can say when and from where but never who. Receiving a secret never needs an account either way. |
|
|
|
|
Turning this on makes creation an unauthenticated write, bounded at 10 links per
|
|
address per 10 minutes. A signed-in user still needs the `tools.secrets`
|
|
permission, so a member without it cannot create one while a guest can - opening
|
|
the door to guests is a decision about the door, not about revoking what a role
|
|
holds. The setting fails closed if it cannot be read.
|
|
|
|
See [SECURE-SEND.md](SECURE-SEND.md) for the whole feature, including why the
|
|
server cannot recover a secret and what the size limit is doing.
|
|
|
|
### identifiers (dynamic)
|
|
|
|
One boolean key per asset identifier per asset type, keyed
|
|
`identifier_<name>_<assettype>_enabled` (default `true`). Admins choose which
|
|
optional identifiers show on which asset types. See ADR-001. The exact set is
|
|
generated from `IDENTIFIER_LABELS` x `IDENTIFIER_ASSETTYPES` in
|
|
`shopdb/core/api/settings.py`.
|
|
|
|
### search (dynamic)
|
|
|
|
One boolean key per search domain, keyed `search_<type>_enabled` (default
|
|
`true`). Toggles whether a domain appears in global search results. The set is
|
|
generated from `SEARCH_DOMAINS` in `shopdb/core/api/settings.py`.
|
|
|
|
Search terms are matched word-wise: a multi-word query returns rows containing
|
|
EVERY word, each word anywhere in the searched fields, in any order ("CSF Roles"
|
|
matches a row with "CSF" and "Roles" in different columns). Quoting does not
|
|
force a contiguous phrase.
|
|
|
|
## Custom fields
|
|
|
|
Site-defined extra attributes per asset type (Settings > Custom Fields, table
|
|
`customfields`). Each field has a `searchable` flag (default off). When on, the
|
|
field's stored values are matched by global search and a hit routes to the
|
|
owning asset's detail page. The asset's `search_<type>_enabled` domain toggle
|
|
still applies, so a custom-field hit on a computer only shows when the computer
|
|
search domain is enabled. Inactive or non-searchable fields are never matched.
|
|
|
|
---
|
|
|
|
## See also
|
|
|
|
- [DEPLOY.md](DEPLOY.md) - per-site deployment runbook
|
|
- [UPGRADE.md](UPGRADE.md) - upgrading an existing site
|
|
- [BACKUP-RESTORE.md](BACKUP-RESTORE.md) - backup and restore
|
|
- `shopdb/config.py` - authoritative env-var definitions
|
|
- `shopdb/core/api/settings.py` (`build_default_settings`) - authoritative Setting defaults
|