@tpsdev-ai/flair 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -6
- package/dist/cli.js +227 -71
- package/dist/resources/AdminPrincipals.js +10 -1
- package/dist/resources/Agent.js +105 -11
- package/dist/resources/AgentSeed.js +10 -2
- package/dist/resources/MemoryUsage.js +18 -0
- package/dist/resources/Presence.js +8 -1
- package/dist/resources/agent-admin.js +149 -0
- package/dist/resources/agent-auth.js +98 -5
- package/dist/resources/auth-middleware.js +92 -19
- package/dist/resources/in-process-api.js +382 -0
- package/dist/resources/in-process.js +9 -0
- package/dist/resources/mcp-handler.js +14 -4
- package/dist/resources/presence-internal.js +6 -1
- package/dist/resources/record-owner-guard.js +149 -0
- package/docs/deployment-shapes.md +35 -0
- package/docs/deployment.md +2 -2
- package/docs/embedding-in-a-harper-app.md +174 -75
- package/docs/hosted-on-fabric.md +203 -0
- package/docs/secrets-and-keys.md +4 -4
- package/docs/standalone-local.md +243 -0
- package/docs/upgrade.md +7 -3
- package/package.json +7 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Hosted on Harper Fabric
|
|
2
|
+
|
|
3
|
+
Deploy Flair as a component to a [Harper Fabric](https://www.harperdb.io/) instance. You do not run the Harper process yourself: managed hosting, multi-region replication, no shell on the node.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Deploy
|
|
8
|
+
|
|
9
|
+
You **deploy** rather than install. `flair deploy` pushes Flair as a Fabric component:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
export FABRIC_USER=<admin> FABRIC_PASSWORD=<pass>
|
|
13
|
+
|
|
14
|
+
# Validate args and package layout without deploying
|
|
15
|
+
flair deploy --fabric-org <org> --fabric-cluster <cluster> --dry-run
|
|
16
|
+
|
|
17
|
+
# Deploy
|
|
18
|
+
flair deploy --fabric-org <org> --fabric-cluster <cluster>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Credentials go via the environment, not argv, so they stay out of `ps`. Use `--fabric-password-file <path>` (mode `0600`) when scripting; inline `--fabric-user`/`--fabric-password` flags leak to shell history and are discouraged.
|
|
22
|
+
|
|
23
|
+
Target defaults to `https://<cluster>.<org>.harperfabric.com`; override with `--target`. Deploy verifies the served API, waits for replication, and polls for convergence before reporting success.
|
|
24
|
+
|
|
25
|
+
> `--fabric-token` is accepted but **fails** — `deploy_component` is Basic-auth only.
|
|
26
|
+
|
|
27
|
+
### Provision the instance
|
|
28
|
+
|
|
29
|
+
Run **once**, before serving traffic:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
flair init --target https://<cluster>.<org>.harperfabric.com \
|
|
33
|
+
--ops-target <ops-url> \
|
|
34
|
+
--cluster-admin-user <user> --cluster-admin-pass <pass> \
|
|
35
|
+
--remote --force
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- `--force` is required — this writes to a live instance.
|
|
39
|
+
- `--remote` marks it a federation **hub** and creates the `flair_pair_initiator` role; without it, pairing later fails role-not-found.
|
|
40
|
+
- Generated admin password lands in `~/.tps/secrets/flair-fabric-hdb` (mode `0600`); `--flair-admin-pass` to choose your own.
|
|
41
|
+
|
|
42
|
+
### Port derivation trap
|
|
43
|
+
|
|
44
|
+
Locally, Flair serves data on `19926` and the ops API on `19925`. The CLI derives **ops = data − 1** everywhere. A managed endpoint is HTTPS on 443 with no port, so derivation produces `:442` — where nothing answers.
|
|
45
|
+
|
|
46
|
+
**Pass `--ops-target <url>` explicitly** (or set `FLAIR_OPS_TARGET`) on any command that touches the ops API: `init --target`, `agent add --target`, `federation token --target`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
On Fabric, configuration goes through the component's environment, not a local `config.yaml`. Set these in the Fabric component env:
|
|
53
|
+
|
|
54
|
+
| Variable | What it does | When to set it |
|
|
55
|
+
|----------|--------------|----------------|
|
|
56
|
+
| `FLAIR_PUBLIC_URL` | The URL operators reach this Flair on. Surfaced in OAuth metadata and A2A discovery. | **Always set** — or clients see a loopback address. |
|
|
57
|
+
| `HDB_ADMIN_PASSWORD` | Bootstrap password for the embedded Harper. | Set at install time. |
|
|
58
|
+
| `FLAIR_KEY_PASSPHRASE` | Passphrase for federation key encryption. | Set for production federation deployments. |
|
|
59
|
+
|
|
60
|
+
On Fabric / managed deploys, environment variables are provisioned through Harper's Fabric secrets mechanism (encrypted at rest with `enc:v1:` storage format).
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Agent authentication
|
|
65
|
+
|
|
66
|
+
Agents authenticate with **Ed25519 per-agent keys** — the same model as standalone local. Each agent holds a private key and signs every request.
|
|
67
|
+
|
|
68
|
+
### Register an agent
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Register an agent — --ops-target is required (see Port derivation trap above)
|
|
72
|
+
flair agent add mybot --target "$FLAIR_URL" --ops-target <ops-url>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The private key is stored on the **client machine** at `~/.flair/keys/<agent>.key`, not on the Fabric node. The Fabric node stores only the public key in the `Agent` table.
|
|
76
|
+
|
|
77
|
+
### Connect a client
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
export FLAIR_URL=https://<cluster>.<org>.harperfabric.com
|
|
81
|
+
|
|
82
|
+
# Register an agent
|
|
83
|
+
flair agent add mybot --target "$FLAIR_URL" --ops-target <ops-url>
|
|
84
|
+
|
|
85
|
+
# Use with any MCP client — set FLAIR_AGENT_ID and FLAIR_URL in the client env
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Auth is the same protocol as standalone: Ed25519 signature of `agentId:timestamp:nonce:METHOD:/path`, 30-second replay window, nonce deduplication. The difference is purely the transport — HTTPS instead of localhost HTTP.
|
|
89
|
+
|
|
90
|
+
See [secrets-and-keys.md](secrets-and-keys.md) for the full threat model.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Verify it works
|
|
95
|
+
|
|
96
|
+
### Health and status
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
curl -sf https://<cluster>.<org>.harperfabric.com/Health
|
|
100
|
+
|
|
101
|
+
flair status --target https://<cluster>.<org>.harperfabric.com
|
|
102
|
+
flair fleet verify --target https://<cluster>.<org>.harperfabric.com
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`fleet verify` checks health, auth, and version across the origin node plus every Flair federation peer on file. Exit codes: 0 = all verified, 1 = origin failed, 2 = peer version skew, 3 = peer unverifiable.
|
|
106
|
+
|
|
107
|
+
> **A credential mismatch renders as an empty section.** `flair status` reads `/HealthDetail` with `FLAIR_ADMIN_PASS` / `HDB_ADMIN_PASSWORD` / a pinned agent key — **not** the `FABRIC_*` credentials. On failure it renders blank.
|
|
108
|
+
|
|
109
|
+
### What is available remotely
|
|
110
|
+
|
|
111
|
+
| Command | Works remotely |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `GET /Health` | Yes — public, no auth |
|
|
114
|
+
| `flair status --target <url>` | Yes — subsystem rollups |
|
|
115
|
+
| `flair quality --target <url>` | Yes — recall/coverage metrics |
|
|
116
|
+
| `flair fleet verify --target <url>` | Yes — origin + Flair peers |
|
|
117
|
+
| `flair federation status\|verify\|reachability --target <url>` | Yes — peer table, sync recency |
|
|
118
|
+
|
|
119
|
+
### What does **not** work remotely
|
|
120
|
+
|
|
121
|
+
**`flair doctor`** takes no `--target` — it hardcodes localhost, reads a local PID file, and shells out to `lsof`. Unavailable too: `start`, `stop`, `restart`, `snapshot`, `reembed`, `rem`, `bridge`.
|
|
122
|
+
|
|
123
|
+
**Fabric's own cluster topology is invisible.** `fleet verify` sweeps *Flair's* federation peer table, not Harper's cluster nodes. `cluster_status` is harper-pro-only. `0 peers known` means "0 on file", never "0 exist."
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Upgrade
|
|
128
|
+
|
|
129
|
+
A Fabric-deployed Flair is a component, not an npm package. Upgrade in place:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
FABRIC_USER=<admin> FABRIC_PASSWORD=<pass> \
|
|
133
|
+
flair upgrade --target https://<cluster>.<org>.harperfabric.com
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
This resolves the target version, stages a clean deployable with the required `@harperfast/harper` version pin, confirms the staged build before deploying, pushes it via `flair deploy`, and verifies the result. After a successful deploy, it runs a fleet convergence sweep across the origin plus every Flair federation peer.
|
|
137
|
+
|
|
138
|
+
- `--check` shows the version diff and plan without deploying.
|
|
139
|
+
- `--yes` skips the confirmation prompt for scripted use.
|
|
140
|
+
- `--fabric-password-file <path>` reads the password from a file instead of an env var.
|
|
141
|
+
- `--no-fleet-verify` skips the post-deploy fleet sweep.
|
|
142
|
+
|
|
143
|
+
Inline `--fabric-user`/`--fabric-password` flags also work but are **discouraged** — both leak to shell history and `ps`.
|
|
144
|
+
|
|
145
|
+
### Backup before upgrading
|
|
146
|
+
|
|
147
|
+
`flair snapshot` is local-only. Back up before every upgrade:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
flair backup --url https://<cluster>.<org>.harperfabric.com \
|
|
151
|
+
--admin-pass-file <path> --output ./flair-backup.json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
See [upgrade.md](upgrade.md#upgrading-a-fabric-deployed-instance) for the full walkthrough.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Federation
|
|
159
|
+
|
|
160
|
+
Available. Pair a local spoke to a Fabric-hosted hub:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# On any machine (no shell on the hub) — generate a pairing token triple
|
|
164
|
+
FLAIR_ADMIN_PASS=<hub-admin-password> flair federation token \
|
|
165
|
+
--target https://<cluster>.<org>.harperfabric.com \
|
|
166
|
+
--ops-target <ops-url> > ./pair-triple.json
|
|
167
|
+
|
|
168
|
+
# On the spoke — pair to the Fabric hub
|
|
169
|
+
flair federation pair https://<cluster>.<org>.harperfabric.com \
|
|
170
|
+
--token-from ./pair-triple.json
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Pairing limitation
|
|
174
|
+
|
|
175
|
+
The scheduled sync driver (`flair federation sync enable`) writes a launchd job or systemd timer **on the machine running the CLI** — it cannot be installed on a Fabric node. A periodic one-shot from the spoke machine is the workaround.
|
|
176
|
+
|
|
177
|
+
Full walkthrough: [federation.md](federation.md).
|
|
178
|
+
|
|
179
|
+
### Multi-region replication
|
|
180
|
+
|
|
181
|
+
Fabric gives you N regional nodes running one component — **not** N Flair instances. Every node shares one Flair identity (the `Instance` table replicates). You do **not** federate your own regions to each other — Harper replication handles that. Use `flair federation pair` only to reach a **separate** Flair instance.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Known operational limitations
|
|
186
|
+
|
|
187
|
+
### No disk or quota telemetry
|
|
188
|
+
|
|
189
|
+
`flair status` reports usage for two directories: no free space, no total, no quota. An instance can hit its quota with nothing saying so. The one indirect signal is a migration halting for space.
|
|
190
|
+
|
|
191
|
+
### Unbounded npm cache
|
|
192
|
+
|
|
193
|
+
Every deploy runs a server-side `npm install` using the node's default cache. npm never evicts it, so it grows until it fills the quota. There is no cache flag, alternate location, or cleanup option. [flair#886](https://github.com/tpsdev-ai/flair/issues/886).
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## See also
|
|
198
|
+
|
|
199
|
+
- [deployment-shapes.md](deployment-shapes.md) — choose your shape
|
|
200
|
+
- [upgrade.md](upgrade.md#upgrading-a-fabric-deployed-instance) — full Fabric upgrade walkthrough
|
|
201
|
+
- [federation.md](federation.md) — pairing, sync driver, conflict resolution
|
|
202
|
+
- [standalone-local.md](standalone-local.md) — the standalone shape (different upgrade, shell available)
|
|
203
|
+
- [secrets-and-keys.md](secrets-and-keys.md) — admin password, key lifecycle
|
package/docs/secrets-and-keys.md
CHANGED
|
@@ -7,11 +7,11 @@ Flair owns **identity**. Flair does **not** own arbitrary secrets. This page dra
|
|
|
7
7
|
For each registered agent, Flair stores:
|
|
8
8
|
|
|
9
9
|
- A **public key** in the `Agent` table (server-side; used to verify signed requests).
|
|
10
|
-
- A **private key** at `~/.flair/keys/<agent>.key` on the host that owns that agent
|
|
10
|
+
- A **private key** at `~/.flair/keys/<agent>.key` on the host that owns that agent — the raw 32-byte Ed25519 seed. Created by `flair init --agent <id>` or `flair agent add <id>`. Mode `0600`.
|
|
11
11
|
|
|
12
12
|
Agents sign every request to Flair with this key. Flair refuses unsigned requests and refuses signatures that don't match the registered public key. The signed payload is `<agentId>:<timestamp>:<nonce>:<METHOD>:<path>` with a 30-second replay window and nonce dedup — replays inside that window are rejected.
|
|
13
13
|
|
|
14
|
-
**This is the only secret material Flair manages.** Lose the key file and the agent is locked out (`flair agent rotate <id>` to issue a new pair).
|
|
14
|
+
**This is the only secret material Flair manages.** Lose the key file and the agent is locked out (`flair agent rotate-key <id>` to issue a new pair).
|
|
15
15
|
|
|
16
16
|
## Flair admin password (Harper instance)
|
|
17
17
|
- If not provided via `--admin-pass`, `--admin-pass-file`, `FLAIR_ADMIN_PASS`, or `HDB_ADMIN_PASSWORD`, a random password is generated and written to `~/.flair/admin-pass` (mode `0o600`). The password is **not** printed to the console.
|
|
@@ -140,7 +140,7 @@ Hermes uses `~/.hermes/.env` for provider API keys (managed by `hermes auth`). T
|
|
|
140
140
|
|
|
141
141
|
- **Stays on the host that owns the agent.** If your agent runs on a given host, the key lives on that host. If you spin up the same agent on another machine, **don't copy the key** — register a new agent identity (`flair agent add <id>-on-<other-host>`) on that machine. Different identities, same Flair instance can store memories for both, you decide cross-agent visibility.
|
|
142
142
|
- **`chmod 600` enforced** by `flair agent add`. Don't relax it.
|
|
143
|
-
- **Don't check it into git.** `.gitignore` should already exclude `~/.flair/keys/`; if you're ever tempted to share keys for "convenience," rotate first (`flair agent rotate <id>`).
|
|
143
|
+
- **Don't check it into git.** `.gitignore` should already exclude `~/.flair/keys/`; if you're ever tempted to share keys for "convenience," rotate first (`flair agent rotate-key <id>`).
|
|
144
144
|
- **Backup separately**, encrypted. The `flair backup` command excludes private keys by default. Roll your own backup of `~/.flair/keys/` via age-encrypted archive if you want offsite recovery.
|
|
145
145
|
|
|
146
146
|
## What about a `flair secret` CLI?
|
|
@@ -153,7 +153,7 @@ If you find yourself wanting one anyway, your agent can call `security find-gene
|
|
|
153
153
|
|
|
154
154
|
| Asset | Owned by | If compromised → |
|
|
155
155
|
|---|---|---|
|
|
156
|
-
| Flair agent private key (`~/.flair/keys/<agent>.key`) | Flair (you, on the host) | Attacker can **write** memories under that agent's identity and read that agent's **`private`**-marked memories until you rotate. Use `flair agent rotate <id>`. Other agents' write identity is unaffected — they can't be impersonated with this key. |
|
|
156
|
+
| Flair agent private key (`~/.flair/keys/<agent>.key`) | Flair (you, on the host) | Attacker can **write** memories under that agent's identity and read that agent's **`private`**-marked memories until you rotate. Use `flair agent rotate-key <id>`. Other agents' write identity is unaffected — they can't be impersonated with this key. |
|
|
157
157
|
| LLM provider API keys (Anthropic, OpenAI, etc.) | OS keyring / 1Password | Standard provider revocation: rotate the key in the provider's console, update keyring entry. |
|
|
158
158
|
| Cross-host secrets (1Password vault, age-sops) | The secret manager itself | Trust falls back to that manager's MFA / key handling. Document recovery in your team's ops runbook. |
|
|
159
159
|
| Memory contents | Flair (server-side) | Write access requires the owning agent's key → see "Per-agent write isolation, org-wide non-private read" below. |
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Standalone Local Deployment
|
|
2
|
+
|
|
3
|
+
`flair init` installs and runs its own Harper process. This is the default path and what most operators use: a single process on a single machine, no Fabric, no external services.
|
|
4
|
+
|
|
5
|
+
If you're starting from zero, begin with the [quickstart](quickstart.md). This page covers the full lifecycle: install, configuration, authentication, verification, and upgrade.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install & deploy
|
|
10
|
+
|
|
11
|
+
**Prerequisites:** Node.js 22+ (LTS or current). No Docker, no database, no API keys.
|
|
12
|
+
|
|
13
|
+
### 1. Install the CLI
|
|
14
|
+
|
|
15
|
+
Use a **user-writable npm prefix** so the package directory is owned by you. A root-owned install (`sudo npm install -g`) breaks the embeddings component at runtime:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
mkdir -p ~/.npm-global
|
|
19
|
+
npm config set prefix ~/.npm-global
|
|
20
|
+
export PATH="$HOME/.npm-global/bin:$PATH" # add to your shell rc to persist
|
|
21
|
+
|
|
22
|
+
npm install -g @tpsdev-ai/flair
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> ⚠️ **Never `sudo npm install -g @tpsdev-ai/flair`.** A root-owned install makes the package directory unwritable by the user Harper runs as. At runtime the embeddings component gets `EACCES` and semantic search silently degrades to keyword-only. `flair init` and `flair doctor` will warn you loudly.
|
|
26
|
+
|
|
27
|
+
### 2. Bootstrap the instance
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
flair init
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`flair init` does everything in one step:
|
|
34
|
+
|
|
35
|
+
1. Installs the embedded Harper (memory store) into `~/.flair/data/`.
|
|
36
|
+
2. Downloads the local embedding model (~80 MB — first run only).
|
|
37
|
+
3. Starts Flair as a launchd / systemd service on port `19926`.
|
|
38
|
+
4. Creates a default agent identity (Ed25519 keypair, stored at `~/.flair/keys/<agent>.key`).
|
|
39
|
+
5. Runs a smoke test to confirm semantic search works.
|
|
40
|
+
|
|
41
|
+
Useful flags:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
flair init --agent mybot # name the agent (--agent-id also works)
|
|
45
|
+
flair init --client claude-code # wire one specific MCP client
|
|
46
|
+
flair init --no-mcp # instance + agent only, skip MCP wiring
|
|
47
|
+
flair init --skip-smoke # skip the MCP smoke test
|
|
48
|
+
flair init --port 8000 # use a non-default port
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
> **Non-interactive shell:** bare `flair init` with no `--agent` bootstraps the instance only and skips agent registration, MCP client wiring, and the smoke test. Pass flags explicitly: `flair init --agent <id> --client all`.
|
|
52
|
+
|
|
53
|
+
### 3. Lifecycle management
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
flair status # check everything is working
|
|
57
|
+
flair stop # stop the service (keeps data)
|
|
58
|
+
flair restart # restart the service
|
|
59
|
+
flair uninstall # remove the service (keeps data + keys)
|
|
60
|
+
flair uninstall --purge # remove everything including data and keys
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
On macOS the service is a launchd plist at `~/Library/LaunchAgents/ai.tpsdev.flair.plist`. On Linux it is a systemd unit at `~/.config/systemd/user/flair.service`. Both auto-start on login/boot and restart on crash.
|
|
64
|
+
|
|
65
|
+
### Docker
|
|
66
|
+
|
|
67
|
+
Flair does not have a foreground daemon mode today (`flair start` has no `--foreground` option and `flair init` always installs a service manager unit). There is no supported Docker recipe — run Flair directly on the host or use [Harper Fabric](https://www.harperdb.io/) for managed hosting.
|
|
68
|
+
|
|
69
|
+
Embeddings run on CPU in any containerized environment (no Metal acceleration). Performance is acceptable for small-to-medium memory stores (< 10K memories).
|
|
70
|
+
|
|
71
|
+
See also: [system-requirements.md](system-requirements.md) for measured resource usage.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Configuration
|
|
76
|
+
|
|
77
|
+
All configuration lives in `~/.flair/`:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
~/.flair/
|
|
81
|
+
├── config.yaml # port, host, embedding model
|
|
82
|
+
├── data/ # Harper database (RocksDB)
|
|
83
|
+
├── keys/ # Ed25519 keypairs per agent (mode 0600)
|
|
84
|
+
└── backups/ # flair backup output
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Key config options (`~/.flair/config.yaml`)
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
http:
|
|
91
|
+
port: 19926 # API port (ops port = this - 1)
|
|
92
|
+
host: 127.0.0.1 # bind address (0.0.0.0 for remote access)
|
|
93
|
+
|
|
94
|
+
clustering:
|
|
95
|
+
nodeName: flair
|
|
96
|
+
|
|
97
|
+
logging:
|
|
98
|
+
level: warn
|
|
99
|
+
stdStreams: true
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Environment variables
|
|
103
|
+
|
|
104
|
+
| Variable | What it does | When to set it |
|
|
105
|
+
|----------|--------------|----------------|
|
|
106
|
+
| `FLAIR_PUBLIC_URL` | The URL operators reach this Flair on. Used by OAuth metadata and A2A discovery. | Set on VPS / internet-facing deployments. |
|
|
107
|
+
| `HDB_ADMIN_PASSWORD` | Bootstrap password for the embedded Harper. After first start, the persisted user record is the source of truth. | Set at install time. See [secrets-and-keys.md](secrets-and-keys.md) for rotation. |
|
|
108
|
+
| `FLAIR_KEY_PASSPHRASE` | Passphrase for AES-256-GCM encryption of federation private-key seeds. | Set explicitly for production federation deployments. |
|
|
109
|
+
| `FLAIR_URL` | Override the Flair base URL for CLI commands (points to a remote instance). | When connecting from a different machine. |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Agent authentication
|
|
114
|
+
|
|
115
|
+
Agents authenticate with **Ed25519 per-agent keys**:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Register an agent (generates Ed25519 keypair at ~/.flair/keys/myagent.key)
|
|
119
|
+
flair agent add myagent
|
|
120
|
+
|
|
121
|
+
# List registered agents
|
|
122
|
+
flair agent list
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Every request to Flair is signed with the agent's private key. The signed payload is `agentId:timestamp:nonce:METHOD:/path` with a 30-second replay window and nonce deduplication. Unsigned requests are rejected.
|
|
126
|
+
|
|
127
|
+
This guarantees **write isolation** (no agent can write as another) and identity-verified reads. Reads are intentionally more open: any verified agent on the same instance can read any other agent's non-private memories. Only `visibility: private` memories are owner-only. See [SECURITY.md](../SECURITY.md) for the full model.
|
|
128
|
+
|
|
129
|
+
### The private key
|
|
130
|
+
|
|
131
|
+
- Lives at `~/.flair/keys/<agent>.key` (PKCS8 base64, mode `0600`).
|
|
132
|
+
- **Stays on the host that owns the agent.** Don't copy it to another machine — register a new agent identity there.
|
|
133
|
+
- **Don't check it into git.** Rotate first if compromised: `flair agent rotate-key <id>`.
|
|
134
|
+
- `flair backup` excludes private keys by default. Back them up separately if you want offsite recovery.
|
|
135
|
+
|
|
136
|
+
See [secrets-and-keys.md](secrets-and-keys.md) for the full threat model and key lifecycle.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Verify it works
|
|
141
|
+
|
|
142
|
+
### Quick health check
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
flair status
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The **🟢** icon means everything is healthy. A **🟡** means something worth looking at; **🔴 unreachable** means the server isn't running.
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
flair status --agent local # full detail: memory counts, soul entries
|
|
152
|
+
flair doctor # automated diagnosis + fix suggestions
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### End-to-end smoke test
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Write a memory
|
|
159
|
+
flair memory add --agent myagent "Harper v5 sandbox blocks node:module but process.dlopen works"
|
|
160
|
+
|
|
161
|
+
# Find it by meaning (not keywords)
|
|
162
|
+
flair memory search --agent myagent "native addon loading in sandboxed runtimes"
|
|
163
|
+
# → [0.67] Harper v5 sandbox blocks node:module but process.dlopen works
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Connectivity
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
curl http://localhost:19926/Health # public, no auth needed
|
|
170
|
+
flair doctor # checks embeddings, auth, connectivity
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
See [troubleshooting.md](troubleshooting.md) for common issues and fixes.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Upgrade
|
|
178
|
+
|
|
179
|
+
`flair upgrade` is install → restart → verify → rollback-on-failure in one step:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# 1. Back up first, always
|
|
183
|
+
flair backup --output ~/flair-backup-$(date +%Y%m%d).json --admin-pass-file ~/.flair/admin-pass
|
|
184
|
+
|
|
185
|
+
# 2. Check what's outdated (doesn't install anything)
|
|
186
|
+
flair upgrade --check
|
|
187
|
+
|
|
188
|
+
# 3. Upgrade — installs, restarts, and verifies in one step
|
|
189
|
+
flair upgrade
|
|
190
|
+
|
|
191
|
+
# 4. Verify
|
|
192
|
+
flair status
|
|
193
|
+
flair doctor
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Optional: `flair upgrade --snapshot` takes a byte-exact snapshot of `~/.flair/data` before upgrading, so you can restore the physical data directory if the new version writes data the old version can't read.
|
|
197
|
+
|
|
198
|
+
See [upgrade.md](upgrade.md) for the full walkthrough including re-embedding, rollback, and downgrade.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Backup & restore
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Backup all data (agents, memories, souls)
|
|
206
|
+
flair backup --output ~/flair-backup-$(date +%Y%m%d).json
|
|
207
|
+
|
|
208
|
+
# Restore to a fresh instance
|
|
209
|
+
flair restore ~/flair-backup-20260405.json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Always backup before upgrades. `flair backup` excludes private keys.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Federation
|
|
217
|
+
|
|
218
|
+
Available. Pair a local instance as a hub or spoke with another Flair instance:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# On the hub — generate a one-time pairing token triple
|
|
222
|
+
FLAIR_ADMIN_PASS=<hub-admin-password> flair federation token > triple.json
|
|
223
|
+
|
|
224
|
+
# On the spoke — pair to the hub
|
|
225
|
+
flair federation pair <hub-url> --token-from ./triple.json
|
|
226
|
+
|
|
227
|
+
# Sync (one-shot)
|
|
228
|
+
flair federation sync --admin-pass-file ~/.flair/admin-pass
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Full walkthrough: [federation.md](federation.md).
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## See also
|
|
236
|
+
|
|
237
|
+
- [deployment-shapes.md](deployment-shapes.md) — choose your shape
|
|
238
|
+
- [quickstart.md](quickstart.md) — zero to working in 5 minutes
|
|
239
|
+
- [upgrade.md](upgrade.md) — full upgrade mechanics (re-embedding, rollback, downgrade)
|
|
240
|
+
- [federation.md](federation.md) — hub-and-spoke sync between instances
|
|
241
|
+
- [troubleshooting.md](troubleshooting.md) — common issues and automated diagnosis
|
|
242
|
+
- [system-requirements.md](system-requirements.md) — measured resource usage
|
|
243
|
+
- [secrets-and-keys.md](secrets-and-keys.md) — agent keys, admin password, threat model
|
package/docs/upgrade.md
CHANGED
|
@@ -17,7 +17,11 @@ There are two things you might be upgrading:
|
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
# 1. Back up first, always
|
|
20
|
-
|
|
20
|
+
# --admin-pass-file keeps the secret out of ps and shell history.
|
|
21
|
+
# --output is required — the archive goes to a file, not stdout.
|
|
22
|
+
flair backup \
|
|
23
|
+
--output ~/flair-backup-$(date +%Y%m%d).json \
|
|
24
|
+
--admin-pass-file ~/.flair/admin-pass
|
|
21
25
|
|
|
22
26
|
# 2. Check what's outdated (doesn't install anything)
|
|
23
27
|
flair upgrade --check
|
|
@@ -188,7 +192,7 @@ FABRIC_USER=<admin> FABRIC_PASSWORD=<pass> \
|
|
|
188
192
|
|
|
189
193
|
(or `--fabric-password-file <path>` instead of the `FABRIC_PASSWORD` env var — reads the
|
|
190
194
|
password from a file, chmod 600). This resolves the target version (latest published
|
|
191
|
-
`@tpsdev-ai/flair`, or pin one with `--version`), stages a clean deployable with the
|
|
195
|
+
`@tpsdev-ai/flair`, or pin one with `--flair-version`), stages a clean deployable with the
|
|
192
196
|
required `harper` version pin applied (`--harper-version` to override),
|
|
193
197
|
confirms the staged Harper build before deploying, then reuses `flair deploy` to push it
|
|
194
198
|
and verifies the result. `--check` shows the version diff and plan without deploying
|
|
@@ -352,7 +356,7 @@ npm install -g @tpsdev-ai/flair@<previous-version>
|
|
|
352
356
|
flair restart
|
|
353
357
|
|
|
354
358
|
# If data looks wrong, restore from your pre-upgrade backup
|
|
355
|
-
flair restore
|
|
359
|
+
flair restore ~/flair-backup-<date>.json
|
|
356
360
|
```
|
|
357
361
|
|
|
358
362
|
`flair upgrade` does this automatically on a failed post-restart verification — see
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tpsdev-ai/flair",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"packageManager": "bun@1.3.10",
|
|
5
5
|
"description": "Identity, memory, and soul for AI agents. Cryptographic identity (Ed25519), semantic memory with local embeddings, and persistent personality — all in a single process.",
|
|
6
6
|
"type": "module",
|
|
@@ -25,6 +25,12 @@
|
|
|
25
25
|
"llm",
|
|
26
26
|
"openclaw"
|
|
27
27
|
],
|
|
28
|
+
"main": "./dist/resources/in-process-api.js",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./dist/resources/in-process-api.js",
|
|
31
|
+
"./server": "./dist/resources/in-process.js",
|
|
32
|
+
"./package.json": "./package.json"
|
|
33
|
+
},
|
|
28
34
|
"bin": {
|
|
29
35
|
"flair": "dist/cli-shim.cjs"
|
|
30
36
|
},
|