-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Follow app privacy setting on serve dashboard #2967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d55a1b7
3805441
c666b20
1b149db
1740f50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import Commander | ||
| import Foundation | ||
| import Testing | ||
| @testable import CodexBarCLI | ||
|
|
||
| /// `codexbar serve` resolves dashboard identity per request: an explicit `--identity` pins the | ||
| /// mode, and an absent flag follows the app's "Hide personal information" setting. The resolved | ||
| /// mode also joins the cache key so a body cached before a toggle cannot be replayed after it. | ||
| struct CLIServeDashboardIdentityTests { | ||
| @Test | ||
| func `dashboard identity follows the app privacy setting without a flag`() { | ||
| #expect(CodexBarCLI.resolveDashboardIdentityMode( | ||
| configured: nil, | ||
| hidesPersonalInfo: true) == .redacted) | ||
| #expect(CodexBarCLI.resolveDashboardIdentityMode( | ||
| configured: nil, | ||
| hidesPersonalInfo: false) == .full) | ||
| } | ||
|
|
||
| @Test | ||
| func `dashboard identity flag overrides the app privacy setting`() { | ||
| #expect(CodexBarCLI.resolveDashboardIdentityMode( | ||
| configured: .full, | ||
| hidesPersonalInfo: true) == .full) | ||
| #expect(CodexBarCLI.resolveDashboardIdentityMode( | ||
| configured: .redacted, | ||
| hidesPersonalInfo: false) == .redacted) | ||
| } | ||
|
|
||
| @Test | ||
| func `dashboard identity flag presence separates an explicit full from an absent flag`() { | ||
| #expect(CodexBarCLI.dashboardIdentityFlagPresent(in: ParsedValues( | ||
| positional: [], | ||
| options: ["identity": ["full"]], | ||
| flags: []))) | ||
| #expect(!CodexBarCLI.dashboardIdentityFlagPresent(in: ParsedValues( | ||
| positional: [], | ||
| options: [:], | ||
| flags: []))) | ||
| } | ||
|
|
||
| @Test | ||
| func `an absent identity flag still decodes to the full default`() { | ||
| #expect(CodexBarCLI.decodeDashboardIdentityMode(from: ParsedValues( | ||
| positional: [], | ||
| options: [:], | ||
| flags: [])) == .full) | ||
| } | ||
|
|
||
| @Test | ||
| func `dashboard operation key separates identity modes`() throws { | ||
| let redacted = try CodexBarCLI.serveOperationKey( | ||
| kind: "dashboard-\(DashboardIdentityMode.redacted.rawValue)", | ||
| provider: nil) | ||
| let full = try CodexBarCLI.serveOperationKey( | ||
| kind: "dashboard-\(DashboardIdentityMode.full.rawValue)", | ||
| provider: nil) | ||
|
|
||
| #expect(redacted != full) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,7 +85,7 @@ See `docs/configuration.md` for the schema. | |
| - `--output <path>` atomically writes the snapshot to a file (`0644`) instead of stdout — staged in the destination directory, fsync'd, then renamed over the target so readers never observe a partial document. The parent directory must already exist (it is not created), and stdout stays silent on success. | ||
| - Starts no HTTP server and requires no dashboard bearer token. See `docs/dashboard-api.md` for the shared payload contract. | ||
| - `codexbar serve` starts a foreground HTTP server for usage and cost JSON, a token-gated dashboard snapshot, and a built-in web UI at `/`. | ||
| - Dashboard snapshot identity defaults to full account emails; use `--identity redacted` to hide email local parts, especially when responses cross a network. | ||
| - Dashboard snapshot identity follows the app's "Hide personal information" setting when `--identity` is absent: the toggle on redacts email local parts, off keeps full emails. The setting is read per request, so a change applies without a serve restart. Pass `--identity redacted` or `--identity full` to pin the mode and ignore the app setting, especially when responses cross a network. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This documents the new behavior, but Useful? React with 👍 / 👎. |
||
| - `--host <host>` accepts `localhost` or an IPv4 address and defaults to `127.0.0.1`; `localhost` is normalized to `127.0.0.1`. Binding a non-loopback host requires a dashboard token **and** `--allow-plain-http` (see `docs/dashboard-api.md` for the threat model). | ||
| - `--port <port>` defaults to `8080`. | ||
| - `--refresh-interval <seconds>` defaults to `60` and controls the in-memory response cache TTL. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
serveis launched from a debug app and the release defaults domain already containshidePersonalInfo, this release-first loop always returns that value and never consultscom.steipete.codexbar.debug. Consequently, toggling privacy in the running debug app has no effect on its dashboard. Resolve the domain from the containing app/bundle before reading the setting rather than returning the first value found across both domains.Useful? React with 👍 / 👎.