You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
2 months ago | |
|---|---|---|
| .. | ||
| cmd | 2 months ago | |
| deploy | 2 months ago | |
| internal | 2 months ago | |
| scripts | 2 months ago | |
| vendor | 2 months ago | |
| BROWSER_ANIMATION_DIAGNOSIS_20260909.md | 2 months ago | |
| README.md | 2 months ago | |
| REPLACEMENT_UI_PERFORMANCE_20260909.md | 2 months ago | |
| STARTUP_TIMING.md | 2 months ago | |
| WCH_BOOT_STALL_20260909.md | 2 months ago | |
| go.mod | 2 months ago | |
| go.sum | 2 months ago | |
README.md
tera-api
Initial mock backend for TERA Core-X48 PRO management APIs.
First user task
Portable Go is installed under the repository .tools/ directory. Run:
cd services\tera-api
powershell -NoProfile -ExecutionPolicy Bypass -File ..\..\scripts\use-go.ps1 test ./...
powershell -NoProfile -ExecutionPolicy Bypass -File ..\..\scripts\use-go.ps1 run ./cmd/tera-api
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-linux-arm64-build.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-linux-arm64-build.ps1 -Command tera-logd
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-linux-arm64-build.ps1 -Command tera-hwd
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-linux-arm64-build.ps1 -Command tera-seriald
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-linux-arm64-build.ps1 -Command tera-serial-check
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-linux-arm64-build.ps1 -Command tera-serial-line-check
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-linux-arm64-serial-termios.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-target-rootfs-staging.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\check-target-rootfs-staging.ps1 -InitSystem buildroot
For a same-origin Direct Mode attachment load against a deployed target, keep
the web password in the process environment and run the dedicated client. The
client sends the browser-required Origin header and tera.direct.v1
subprotocol, consumes one-use stream tickets, keeps reading to service
WebSocket heartbeats, validates one welcome frame for every attachment, checks
the matching channel session logs, and closes every session during cleanup.
With -attachments 48, every CH01-CH48 channel is covered once without sending
serial payload; 192 covers four viewers per channel:
$env:TERA_TARGET_PASSWORD = '<read from the protected lab credential source>'
powershell -NoProfile -ExecutionPolicy Bypass -File ..\..\scripts\use-go.ps1 run ./cmd/tera-target-session-load -base-url http://192.168.0.223:8083 -attachments 192 -hold-seconds 60
Remove-Item Env:\TERA_TARGET_PASSWORD
Then verify:
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/system/status
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/system/services
Invoke-RestMethod -Method Post -ContentType 'application/json' -Body '{"username":"admin","password":"mock-admin-secret"}' http://127.0.0.1:8080/api/v1/auth/login
Invoke-RestMethod -Method Post -Headers @{"Authorization"="Bearer <session-token>"} http://127.0.0.1:8080/api/v1/auth/logout
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/auth/me
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/auth/tokens
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"name":"automation"}' http://127.0.0.1:8080/api/v1/auth/tokens
Invoke-RestMethod -Method Delete -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/auth/tokens/token_000001
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/auth/users
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"username":"fieldops","password":"fieldops-secret-1","role":"port_operator"}' http://127.0.0.1:8080/api/v1/auth/users
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"enabled":false}' http://127.0.0.1:8080/api/v1/auth/users/fieldops
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"password":"fieldops-secret-2"}' http://127.0.0.1:8080/api/v1/auth/users/fieldops/password
Invoke-RestMethod -Method Delete -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/auth/users/fieldops
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/auth/groups
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/auth/permissions
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/config/status
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/config/export
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/time/settings
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"timezone":"Asia/Seoul","ntp_servers":["time1.example.local","time2.example.local"]}' http://127.0.0.1:8080/api/v1/time/settings
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/security/management-access
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"https_enabled":true,"https_port":8443,"ssh_enabled":true,"ssh_port":2222,"http_enabled":false,"http_port":80,"telnet_enabled":false,"telnet_port":23,"idle_timeout_minutes":30}' http://127.0.0.1:8080/api/v1/security/management-access
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"interfaces":[{"name":"Interface-1","address":"192.168.10.233/24","gateway":"192.168.10.1"}]}' http://127.0.0.1:8080/api/v1/network/running
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/ports
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/alarms/rules
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"mode":"Reverse Telnet"}' http://127.0.0.1:8080/api/v1/ports/CH01
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"enabled":false}' http://127.0.0.1:8080/api/v1/alarms/rules/auth_failures
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/config/apply
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"browser_time":"2026-06-16T10:31:12+09:00","timezone":"Asia/Seoul"}' http://127.0.0.1:8080/api/v1/time/sync-browser
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/time/sync-ntp
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"target":"192.168.0.1"}' http://127.0.0.1:8080/api/v1/diagnostics/network-test
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"target":"8.8.8.8","count":4}' http://127.0.0.1:8080/api/v1/diagnostics/network-test
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/diagnostics/support-bundle
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} 'http://127.0.0.1:8080/api/v1/logs/audit?actor=admin&order=desc&limit=100'
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} 'http://127.0.0.1:8080/api/v1/logs/system?severity=warning&keyword=failover&from=2026-06-15T00:00:00Z&to=2026-06-17T00:00:00Z'
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} 'http://127.0.0.1:8080/api/v1/logs/port?channel=CH01&keyword=LOGIN&actor=admin&from=2026-06-15T00:00:00Z&to=2026-06-17T00:00:00Z'
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} 'http://127.0.0.1:8080/api/v1/logs/links?kind=serial&resource=CH01'
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/logs/policy
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/logs/retention
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"port_days":180,"protected_usage_warning_pct":85}' http://127.0.0.1:8080/api/v1/logs/retention
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/logs/remote-syslog
Invoke-RestMethod -Method Patch -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"enabled":true,"host":"syslog.local","port":1514,"protocol":"tcp","facility":"local4"}' http://127.0.0.1:8080/api/v1/logs/remote-syslog
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"log_type":"port","channel":"CH01"}' http://127.0.0.1:8080/api/v1/logs/export
Invoke-WebRequest -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} -ContentType 'application/json' -Body '{"log_type":"port","channel":"CH01","actor":"admin","from":"2026-06-15T00:00:00Z","to":"2026-06-17T00:00:00Z"}' -OutFile tera-port-logs.jsonl http://127.0.0.1:8080/api/v1/logs/export/download
Invoke-RestMethod -Method Post -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/ports/CH01/restart
Invoke-RestMethod -Headers @{"X-Mock-Actor"="mock-admin"} http://127.0.0.1:8080/api/v1/operations
Current scope
- Mock domain data with optional target-backed local service adapters and bounded file-backed state for host and rootfs verification.
- In-memory
pending/running/persistentconfig transaction state. - JSON request bodies are bounded by
TERA_API_MAX_REQUEST_BYTESand must contain a single JSON value. Oversized bodies returnpayload_too_largewith HTTP 413; malformed or trailing JSON returnsvalidation_failed. - Audit events for user-verifiable command validation. By default these are
in-memory. Set
TERA_API_AUDIT_LOGto a JSON Lines file path to enable bounded file-backed prototype audit storage; setTERA_API_AUDIT_MAX_EVENTSto control the retained event count. - Config transaction state is in-memory by default. Set
TERA_API_CONFIG_STOREto a JSON file path to retain prototype port, alarm, network, time, and log-retentionpending/running/persistentstate acrosstera-apirestarts. Prototype config export returns running, persistent, and pending port/alarm/network/time/log-retention/ management-access/remote-syslog state and requiresconfig.read. - Operation state is in-memory by default. Set
TERA_API_OPERATION_STOREto a JSON file path to retain prototype operation results acrosstera-apirestarts. Operation result lookup and operation history listing requireoperation.read. - Prototype local auth users are in-memory by default. Set
TERA_API_AUTH_STOREto a JSON file path to retain prototype users with nested password KDF records containingalgorithm,version,params,salt, andhash. Local password hashing uses Argon2id by default; the record schema is versioned so a future FIPS-compatiblepbkdf2-hmac-sha256mode can be added without changing the auth store shape. Local user creation and password reset enforce an eight-character minimum by default.TERA_API_MIN_PASSWORD_LENGTHmay raise that policy up to 128 characters but cannot reduce it below eight. The target profile setsTERA_API_AUTH_STORE=/var/lib/tera-api/auth.jsonso provisioned users and disabled bootstrap accounts survive service restarts. - Prototype bearer sessions use crypto-random tokens, store token hashes
in memory, expire after eight hours, and can be revoked through
POST /api/v1/auth/logout. - Prototype API bearer tokens are available behind
auth.read/auth.write. Raw token material is returned only on creation, stored by hash, and bounded byTERA_API_AUTH_MAX_TOKENSwhen configured. Token records are listed by opaquetoken_idwithout exposing raw token material and can be revoked byDELETE /api/v1/auth/tokens/{token_id}. - Prototype local login tracks repeated failures in memory and temporarily locks a normalized username after five failures for 15 minutes. Client responses remain generic; lock details are recorded only in the audit log.
- Prototype local user, group, and permission read APIs are available behind
auth.read. Prototype local user creation, enable/disable updates, and role updates, password resets/deletes are available behindauth.write. These responses intentionally exclude password KDF records, salts, hashes, session tokens, and token hashes. Deleting or demoting the last enabled administrator is rejected to avoid local lockout. Disabling, deleting, changing role, or resetting the password for a local user immediately revokes that user's existing bearer sessions and API bearer tokens. - Prototype audit log reads require
audit.read; onlymock-adminhas this permission in the current mock policy. - System, structured port command/result, and serial/Ethernet link log search
require
log.read; audited log export and NDJSON download requirelog.export.GET /api/v1/logs/policyexposes the 365-day maximum, command/result and link capture, no-at-rest-encryption decision, and enabled bounded UART/Direct Mode payload capture with a 4-KiB per-record maximum. The production environment connectstera-apito the independenttera-logdUnix socket for authoritative reads/writes, retention, health, and filtered NDJSON export. - Mock log retention policy reads require
log.read; updates requireconfig.write, participate in the config transaction, and preserve protected logs across factory reset by policy. All retention values are limited to 1 through 365 days. - In explicit host-prototype mode,
TERA_API_SYSTEM_LOG_STORE,TERA_API_PORT_LOG_STORE, andTERA_API_LINK_LOG_STOREenable bounded JSON Lines prototype persistence;TERA_API_LOG_MAX_EVENTSbounds each of those stores. Command and result fields are credential-redacted and size-bounded before persistence. A configured/enabled remote syslog target receives best-effort forwarded records through the existing alarm-delivery boundary. - Target packaging instead sets
TERA_API_LOG_SOCKETto/run/tera-logd/log-store.sockand enables the production scheduler withTERA_API_LOG_SCHEDULER_ENABLED=true. It must not configure the prototype JSON Lines paths at the same time. - Mock remote syslog reads require
log.read; updates requireconfig.write, participate in the config transaction, and intentionally contain no shared secrets or credentials. - Mock alarm rule read/update endpoints are available for Web UI flow
validation. Reads require
alarm.read; updates are config transaction changes and requirealarm.write. - Alarm delivery tests call the group-restricted
tera-alarmdUnix socket in target mode.tera-alarmdpersists a bounded retry queue atomically, restores queued/retry-pending work after restart, delivers local/web events, and sends configured remote syslog over UDP or TCP without a shell. SMTP and SNMP trap transports fail explicitly until protected credential storage is implemented; no placeholder secret material is embedded in configuration. - Mock serial channel inventory/detail reads require
port.read. The current mock policy grants it tomock-adminandmock-port-operator. - Mock network state reads require
network.read; onlymock-adminhas this permission in the current mock policy. Mock network interface address/gateway staging requiresnetwork.write, participates in the config transaction, and becomes visible in running state after config apply. - Mock dashboard system status reads require
system.read; onlymock-adminhas this permission in the current mock policy. Mock service health reads use the same permission and report prototype logical service readiness. - Mock config transaction status lookup requires
config.read; onlymock-adminhas this permission in the current mock policy. Mock config export uses the same permission and intentionally excludes auth, session, token, and password KDF material. - Browser/PC time sync requires
time.sync, calls the group-restrictedtera-timedUnix socket, returns an operation result, and records the final audit outcome.tera-timedvalidates the bounded RFC3339 time and IANA timezone, applies/etc/localtimetransactionally, and restores the prior timezone if the Linux clock update fails. The in-process mock is used only when mock actors are explicitly enabled. - Mock time settings read/update is available for maintenance flow validation.
Reads require
config.read; updates requireconfig.writeand participate in the config transaction. - Mock management access policy read/update is available for security flow
validation. Reads require
config.read; updates requireconfig.write, participate in the config transaction, and reject changes that disable every HTTPS, SSH, and serial-console recovery path. - Network-test and traceroute diagnostics require
diagnostics.runand use a bounded asynchronous operation queue in target mode. The process adapter invokes only fixed absoluteping/tracerouteexecutables without a shell, revalidates targets, enforces request timeouts, bounds combined output, and records accepted plus final audit events. Queue/worker counts are bounded and unfinished work is marked failed on restart or shutdown. WhenTERA_API_SUPPORT_BUNDLE_DIRis configured, support-bundle requests use the same bounded queue to create mode-0600ZIP artifacts atomically. Bundles include only system status, service health, redacted config export, bounded audit/system/port events, and operation metadata; auth users, password KDF records, bearer sessions, API token hashes, and secret material are excluded. Artifact count, total bytes, and per-section bytes are bounded. Authorized downloads useGET /api/v1/diagnostics/support-bundles/{bundle_id}withno-store, checksum, and attachment headers and create a download audit. - Green LED control is a real target hardware boundary, not mock serial data:
hardware.readlists the CH01–CH48 PCF8574 mapping andhardware.writeforce/releases or pulses one green LED.tera-apistays unprivileged and calls the group-restrictedtera-hwdUnix socket;tera-hwdalone writes the kernelgpio-ledsbrightness entries after the target DTB is active. - Serial line configuration is routed through the separate
tera-serialdUnix-socket boundary.tera-apinever opens/dev/ttyWCH*. The controller accepts only the validatedfet3568j-c-20260721-v1mapping: CH01-CH24 use/dev/ttyWCH4-/dev/ttyWCH27, and CH25-CH48 use/dev/ttyWCH32-/dev/ttyWCH55. Raw nodes 0-3 and 28-31 are excluded as the unconnected direct CH384 UARTs. Missing or mismatched mapping evidence still fails closed. Seedocs/sw-detail-design/serial-hardware-api-contract.md. - Port updates now stage the bounded full UART profile (supported baud rate,
5-8 data bits, none/even/odd parity, one or two stop bits, and none/RTS-CTS
flow control). Apply operations pass the complete profile to
tera-seriald; readback mismatch or partial failure restores all opened channels. - Mock operation result lookup and operation history listing require
operation.read; onlymock-adminhas this permission in the current mock policy. - Prototype
X-Mock-Actorauth/RBAC skeleton for mutating commands andGET /api/v1/auth/meprofile checks. SetTERA_API_ALLOW_MOCK_ACTORS=falseto disable this header-based prototype bypass and require bearer session or API token authentication for protected routes; CORS preflight responses also stop advertisingX-Mock-Actorwhen this bypass is disabled. - Firmware upload is streamed through the protected
tera-updatedUnix socket;tera-apidoes not own/userdata/updateand cannot mutate partitions or the eMMC layout. The current updater accepts validation-only packages and rejects apply. Read-only diagnostics and explicitly configured remote syslog are the only new external network actions. The only implemented clock mutation crosses the narrowtera-timedlocal socket; HTTP handlers and the unprivilegedtera-apiprocess cannot set the system clock or write/etc/localtimedirectly. - No production login, session token, password hash, external auth secret, or
TLS key storage exists in this prototype. File-backed audit/auth/config/
operation storage is prototype-only and is not a replacement for the
production
tera-logd, product persistent configuration database, protected secret storage, and operation journal paths. Prototype snapshot rewrites do use same-directory temporary files, file and directory sync on Linux, mode0600, atomic rename, and symbolic-link refusal so a crash cannot expose a partially written JSON destination. - API contract is documented in
docs/sw-detail-design/web-api-contract.md. - Backend-to-target implementation and acceptance gates are documented in
docs/sw-detail-design/backend-target-test-gates.md. - Green LED API and deployment details are documented in
docs/sw-detail-design/green-led-api-contract.mdandtarget-bsp/docs/pcf8574-green-led-control.md. - Architecture/FigJam guardrails are documented in
docs/sw-detail-design/architecture-figma-implementation-guardrails.md.
Next implementation steps
- Replace prototype auth/RBAC storage with production session identity and protected token storage. Direct Mode already reuses the common permission and audit path and must not introduce a second auth store.
- Add protected SMTP/SNMP credential storage before enabling those
tera-alarmdtransports. - Replace the remaining prototype config and operation stores with product
persistence; authoritative log persistence is now owned by
tera-logdbut still requires target Stage 4 application and soak evidence. - Keep update/recovery and GPT/eMMC changes disabled until their separate device-side safety and rollback gates are explicitly approved.