Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,11 @@ flicknote daemon restart

`flicknote login` authenticates and then installs, starts, and verifies the user daemon.
`flicknote logout` stops and uninstalls it before clearing the session and local database.
Use `--force` only for explicit recovery when cleanup cannot be confirmed:
After upgrading an existing dev installation for the cnsupa authentication cutover,
run `flicknote login --force` once. This stops and uninstalls the existing daemon,
replaces the old session, and installs, starts, and verifies the daemon again. It
does not delete the local database. `flicknote logout --force` is reserved for
explicit recovery when service cleanup cannot be confirmed:

```bash
flicknote login --force
Expand Down Expand Up @@ -180,6 +184,14 @@ Environment variables:
- `FLICKNOTE_API_URL` — API Worker base URL for share links
- `FLICKNOTE_GATEWAY_URL` — Gateway origin for attachment operations and `gateway request`

For the default `dev` environment, the built-in `FLICKNOTE_SUPABASE_KEY` value
in the [runtime configuration](flicknote-core/src/config.rs) is an opaque cnsupa
publishable key, not the retired JWT-shaped anon key. The value is sent through
Supabase's existing `apikey` header. Existing dev users must upgrade and run
`flicknote login --force` once to replace the old session before normal sync;
explicit config-file and environment key overrides continue to work for custom
environments.

`apiUrl` and `gatewayUrl` can also be set in `config.json`. After changing either
value, restart the daemon with `flicknote daemon restart`. Configure the two
endpoint values together; setting only one is rejected.
Expand Down
6 changes: 6 additions & 0 deletions docs/daemon.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ local state while reporting the unresolved service cleanup.
removing the old session. A failed forced authentication does not restore the
old session or service.

After upgrading an existing dev installation for the cnsupa cutover, run
`flicknote login --force` once before normal sync. The forced login then
authenticates with the opaque publishable key and installs, starts, and verifies
the daemon through the existing lifecycle. It does not automatically delete the
local PowerSync database or perform a release or deployment.

## Service commands

The same commands select a user-level launchd service on macOS and a user-level
Expand Down
32 changes: 30 additions & 2 deletions flicknote-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ fn builtin_defaults(env: &str) -> EndpointDefaults {
),
_ => (
"https://dev-auth.flicknote.app",
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzY1NTM1NTg4LCJleHAiOjE5MjMyMTU1ODh9.7ErMPvghlVm6mew-IKjSShP1Lf6wTCbNgs9ufuh3yqo",
"sb_publishable_4VEs5DX9YlkHuViFbmRMQb_f_LPrdOR",
"https://dev-sync.flicknote.app",
"https://dev-api.flicknote.app/api/v1",
"https://dev-gw.flicknote.app",
Expand Down Expand Up @@ -281,7 +281,32 @@ mod tests {
assert_eq!(defaults.powersync_url, "https://dev-sync.flicknote.app");
assert_eq!(defaults.api_url, "https://dev-api.flicknote.app/api/v1");
assert_eq!(defaults.gateway_url, "https://dev-gw.flicknote.app");
assert!(!defaults.supabase_anon_key.is_empty());
assert_eq!(
defaults.supabase_anon_key,
"sb_publishable_4VEs5DX9YlkHuViFbmRMQb_f_LPrdOR"
);
}

#[test]
fn test_config_load_uses_dev_defaults_without_config() {
with_clean_env(None, || {
let config_home = tempfile::tempdir().expect("config tempdir");
let data_home = tempfile::tempdir().expect("data tempdir");
unsafe {
std::env::set_var("XDG_CONFIG_HOME", config_home.path());
std::env::set_var("XDG_DATA_HOME", data_home.path());
}

let config = Config::load().expect("Config::load should use dev defaults");
assert_eq!(config.supabase_url, "https://dev-auth.flicknote.app");
assert_eq!(
config.supabase_anon_key,
"sb_publishable_4VEs5DX9YlkHuViFbmRMQb_f_LPrdOR"
);
assert_eq!(config.powersync_url, "https://dev-sync.flicknote.app");
assert_eq!(config.api_url, "https://dev-api.flicknote.app/api/v1");
assert_eq!(config.gateway_url, "https://dev-gw.flicknote.app");
});
}

#[test]
Expand All @@ -304,6 +329,7 @@ mod tests {
fn test_env_var_overrides_builtin() {
with_clean_env(None, || {
unsafe { std::env::set_var("FLICKNOTE_SUPABASE_URL", "https://custom.example.com") };
unsafe { std::env::set_var("FLICKNOTE_SUPABASE_KEY", "custom-publishable-key") };
unsafe {
std::env::set_var(
"XDG_CONFIG_HOME",
Expand All @@ -324,6 +350,7 @@ mod tests {
};
let cfg = Config::load().expect("Config::load should succeed");
assert_eq!(cfg.supabase_url, "https://custom.example.com");
assert_eq!(cfg.supabase_anon_key, "custom-publishable-key");
});
}

Expand Down Expand Up @@ -351,6 +378,7 @@ mod tests {
};
let cfg = Config::load().expect("Config::load should succeed");
assert_eq!(cfg.supabase_url, "https://file.example.com");
assert_eq!(cfg.supabase_anon_key, "key");
assert_eq!(cfg.api_url, "https://api.example.com/v1");
assert_eq!(cfg.gateway_url, "https://gateway.example.com");
});
Expand Down