feat: core.preferences persistence helpers — get_user_preference / set_user_preference #22

Closed
opened 2026-04-04 17:38:57 -07:00 by pyr0ball · 0 comments
Owner

Summary

Add get_user_preference(user_id, path) and set_user_preference(user_id, path, value) helpers to circuitforge_core.preferences. All features (affiliate opt-out, BYOK IDs, future per-user settings) read/write through these — no hand-rolled JSON parsing per feature.

Backends

Context Backend
Cloud users Heimdall user_preferences JSON column (GET/PATCH /users/{id}/preferences)
Self-hosted ~/.config/circuitforge/preferences.yaml
Anonymous No persistence — runtime-only dict

Backend is selected automatically based on CF_ORCH_URL / CF_LICENSE_KEY presence.

API

from circuitforge_core.preferences import get_user_preference, set_user_preference

# Read (returns default if path missing)
opted_out = get_user_preference(user_id="u123", path="affiliate.opt_out", default=False)

# Write (immutable merge — returns new preference dict)
set_user_preference(user_id="u123", path="affiliate.byok_ids.ebay", value="my-id")

Dot-path utilities (paths.py) already exist and handle nested read/write.

Blocked on

  • Heimdall#5: user_preferences TEXT DEFAULT '{}' column + GET/PATCH endpoints
  • #21: core.affiliates (primary consumer)
  • Affiliate links design: circuitforge-plans/shared/2026-04-04-affiliate-links-design.md
## Summary Add `get_user_preference(user_id, path)` and `set_user_preference(user_id, path, value)` helpers to `circuitforge_core.preferences`. All features (affiliate opt-out, BYOK IDs, future per-user settings) read/write through these — no hand-rolled JSON parsing per feature. ## Backends | Context | Backend | |---------|--------| | Cloud users | Heimdall `user_preferences` JSON column (GET/PATCH `/users/{id}/preferences`) | | Self-hosted | `~/.config/circuitforge/preferences.yaml` | | Anonymous | No persistence — runtime-only dict | Backend is selected automatically based on `CF_ORCH_URL` / `CF_LICENSE_KEY` presence. ## API ```python from circuitforge_core.preferences import get_user_preference, set_user_preference # Read (returns default if path missing) opted_out = get_user_preference(user_id="u123", path="affiliate.opt_out", default=False) # Write (immutable merge — returns new preference dict) set_user_preference(user_id="u123", path="affiliate.byok_ids.ebay", value="my-id") ``` Dot-path utilities (`paths.py`) already exist and handle nested read/write. ## Blocked on - Heimdall#5: `user_preferences TEXT DEFAULT '{}'` column + GET/PATCH endpoints ## Related - #21: core.affiliates (primary consumer) - Affiliate links design: `circuitforge-plans/shared/2026-04-04-affiliate-links-design.md`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Circuit-Forge/circuitforge-core#22
No description provided.