frontpage-host 0.2.4 → 0.2.6

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/AGENTS.md CHANGED
@@ -260,7 +260,7 @@ Use `frontpage people overview`, `groups`, `stages`, `membership`, `rules`, `att
260
260
 
261
261
  ## Customer Inbox
262
262
 
263
- Internal, allowlisted sites only. Use `frontpage customer-inbox get|put|post RESOURCE`, stable write keys and current versions. Full guide: [CUSTOMER-INBOX.md](./CUSTOMER-INBOX.md). `export CONVERSATION_ID --out FILE` writes authorized paginated history and file metadata; `download FILE_ID --out FILE` downloads through a file grant. Outputs never overwrite existing files. `frontpage usage` reports shared site credits, mail and storage. The owner toolbar uses `manage_customer_inbox` for all site-wide Inbox settings, unlocked knowledge, files, customer conversations, private guidance, replies, takeover/return and recovery. The support agent has a separate server-bound customer scope and requires verification for People data. Both agents cannot edit or unlock locked knowledge; human UI/CLI can unlock it. Never lend a website agent a human CLI key.
263
+ Scale and internal sites, after owner activation. No pilot allowlist. Use `frontpage customer-inbox get|put|post RESOURCE`, stable write keys and current versions. Full guide: [CUSTOMER-INBOX.md](./CUSTOMER-INBOX.md). `export CONVERSATION_ID --out FILE` writes authorized paginated history and file metadata; `download FILE_ID --out FILE` downloads through a file grant. Outputs never overwrite existing files. `frontpage usage` reports shared site credits, mail and storage. The owner toolbar uses `manage_customer_inbox` for all site-wide Inbox settings, unlocked knowledge, files, customer conversations, private guidance, replies, takeover/return and recovery. The support agent has a separate server-bound customer scope and requires verification for People data. Both agents cannot edit or unlock locked knowledge; human UI/CLI can unlock it. Never lend a website agent a human CLI key.
264
264
 
265
265
 
266
266
  Payments, invoices and recurring billing: see packaged [PAYMENTS.md](./PAYMENTS.md), `frontpage help payments`, and https://frontpage.host/developers/payments. Version 0.2.0 removes writable currency, Store checkout mode and Store-owned money commands; Store stays cart-only. Preview/review before sends; keep stable operation keys on retries. Autopay requires the customer’s own verified authorization.
@@ -269,3 +269,5 @@ Payments, invoices and recurring billing: see packaged [PAYMENTS.md](./PAYMENTS.
269
269
  Offerings own every standalone Pay now payment. Use `frontpage payments buttons list|get|create|update|archive|restore`; create the saved offering before adding its returned `data-fp-pay` markup. Supports `--receipt-template-id UUID`, `--default-receipt`, `--active true|false`, combined price/details updates and JSON payloads. Archive deletes from active checkout but preserves history. The website agent uses the same service automatically for ordinary payment-button requests. Store stays cart-only; invoices stay saved customer-addressed records. Full instructions: PAYMENTS.md and https://frontpage.host/developers/payments.
270
270
 
271
271
  Currency is owned by Payments and read by Store, Offerings and invoices. Offering create/get/update responses include exact receiptVariables. For custom confirmations, declare those names with existing mail template commands, attach receiptTemplateId, and verify both records. Only include expressly selected answers; keep private answers excluded. Forms still use input-name tokens and confirmTemplateId.
272
+
273
+ Customer Inbox setup: enable website chat through Inbox settings; Frontpage public sites load it without a file edit or publish. Other websites use the explicit widget snippet. `get website` reports managed addresses/public availability. Website knowledge is default-on, read-only public retrieval; `websiteKnowledge.enabled:false` disables it. Source toggles, attention filtering and receipt cursors use the documented versioned resources.
package/CUSTOMER-INBOX.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Customer Inbox
2
2
 
3
- Customer Inbox uses the site's existing AI credits and storage allowance. It is available on internal plans after site activation. The support agent uses fixed GPT-6 Luna and bills AI usage at 10× raw provider cost. During human handling, customer messages use ordinary routing. Each authenticated owner email uses a small metered Luna Decisions call to keep private guidance, ownership controls and customer-facing replies distinct; the full support agent stays paused. UI and CLI controls need no intent call.
3
+ Customer Inbox uses the site's existing AI credits and storage allowance. It is available on Scale and internal plans after owner activation. Other public plans do not include Inbox. No pilot allowlist is required. The support agent uses fixed GPT-6 Luna and bills AI usage at 10× raw provider cost. During human handling, customer messages use ordinary routing. Normal owner-control email uses a small metered Luna Decisions call to keep private guidance, ownership controls and customer-facing replies distinct; the full support agent stays paused. UI and CLI controls need no intent call.
4
4
 
5
5
  Run `frontpage help customer-inbox`. Use the site's normal CLI key:
6
6
 
@@ -45,9 +45,24 @@ Aliases use 3–48 ASCII letters, numbers and single hyphens. The service normal
45
45
  | `knowledge/<id>/history` | GET | Immutable revisions for that note |
46
46
  | `knowledge` | PUT | `{"title":"Evening visits","body":"Ask the owner before promising an evening visit.","expectedVersion":0,"reason":"Owner policy"}` |
47
47
  | `knowledge/<id>` | PUT | Current title/body, `expectedVersion`, `reason`, optional `locked` or `restoreVersion` |
48
- | `sources` | GET | Approved source records |
48
+ | `sources` | GET | Approved source records; `?overview=true` also includes the latest learning job status |
49
49
  | `sources` | PUT | `{"url":"https://example.com/help","enabled":true,"expectedVersion":0}`; fetches public text |
50
50
 
51
+ The workspace’s **Knowledge** tab separates reusable internal facts from approved webpages. Adding a webpage fetches only that public page’s text; it does not crawl a website or edit an article. Expand **View saved webpage text** to see the snapshot the agent can use. Learning status reports the existing background job; queued does not mean the knowledge update has finished. Open a knowledge note to see its revisions, lock agent changes or restore a version.
52
+
53
+ To enable or disable a saved source without fetching it again, use the owner API:
54
+
55
+ ```http
56
+ POST /api/v1/sites/my-site/customer-inbox/sources/SOURCE_UUID
57
+ Authorization: Bearer <site CLI key>
58
+ Idempotency-Key: source-toggle-001
59
+ Content-Type: application/json
60
+
61
+ {"enabled":false,"expectedVersion":2}
62
+ ```
63
+
64
+ The response data is the same source with `enabled:false` and version `3`; its saved body, digest and check time stay unchanged. Repeat the same key and body after a lost response. A stale version returns `409 source_changed`; a foreign source returns `404`. Disabling prevents future source use and learning, but keeps existing knowledge notes. **Refresh webpage** fetches a fresh snapshot explicitly. The current packaged CLI retains its existing `sources` GET/PUT operations.
65
+
51
66
  Supply `body` on a source write to save an owner-approved excerpt instead of fetching. Published sources refresh when the agent reads a source older than 24 hours. The fetcher reuses Core's DNS-pinned public HTTP infrastructure, rejects private addresses, checks redirects and bounds content. Sources over 16000 text characters require an owner-approved excerpt. No scripts run. A source version/digest fences knowledge updates against a changed source.
52
67
 
53
68
  Knowledge search uses bounded literal keywords from natural-language queries and ranks notes by matched terms. Read the full matching note before updating it; update its current ID/version instead of creating a conflicting duplicate.
@@ -82,10 +97,16 @@ Search results contain previews. The support agent reads the complete matching n
82
97
 
83
98
  Email replies route through opaque, recipient-bound Reply-To addresses linked to the site, conversation, purpose, owner and handler version. These are local addresses on one domain, not a new subdomain per thread. Subjects and message text never select the customer thread. The service checks the exact verified sender, current owner membership, route and receiving-server DMARC proof before interpreting owner mail.
84
99
 
85
- Every owner email and its files enter private custody first. A Luna Decisions call reads the fresh text and bounded, labeled thread context to distinguish guidance, takeover, return, customer reply or unclear input. Use ordinary language to ask to handle the customer, or ask the agent to resume. Questions, quoted commands, negations and future conditions do not transfer control. UI/CLI `control` remains a typed, model-free action. No phrase whitelist controls ownership. A valid but uncertain control answer can use one bounded Luna tool-call fallback. It can choose only private guidance, takeover, return or unclear, with an exact fresh-text excerpt; it cannot authorize a customer reply. Both calls require current credits and distinct once-only receipts. Invalid responses, unknown paid calls and provider outages stay private rather than triggering another inference.
100
+ Every owner email and its files enter private custody first. On normal guidance and owner-control routes, a Luna Decisions call reads the fresh text and bounded, labeled thread context to distinguish guidance, takeover, return, customer reply or unclear input. Use ordinary language to ask to handle the customer, or ask the agent to resume. Questions, quoted commands, negations and future conditions do not transfer control. UI/CLI `control` remains a typed, model-free action. No phrase whitelist controls ownership. A valid but uncertain control answer can use one bounded Luna tool-call fallback. It can choose only private guidance, takeover, return or unclear, with an exact fresh-text excerpt; it cannot authorize a customer reply. Both calls require current credits and distinct once-only receipts. Invalid responses, unknown paid calls and provider outages stay private rather than triggering another inference.
86
101
 
87
102
  Guidance keeps the agent responsible. Takeover sends the owner a separate customer-visible transcript; reply through that relay address so Inbox preserves the history. A customer-facing email creates a separate public message only after a settled decision and current owner-session check. The original intake remains private for audit. Mixed or uncertain input, unavailable inference and exhausted credits stay private with an attention notice. Retry recoverable budget/receipt pauses using the existing job operation; an unknown paid attempt is never inferred again. A fresh reply to the original guidance address can also request return, while stale customer-relay sessions cannot publish.
88
103
 
104
+ Operational support failures and exhausted AI credits use the existing owner takeover. The owner receives a **Customer conversation** email whose body says replies go directly to the customer without AI. These server-marked reply routes relay authenticated owner messages without Decisions or support inference; normal guidance routes remain private. Use the workspace or typed CLI `control` action to return these conversations to the agent. Text sent to a direct-reply route is customer-facing, not an instruction to interpret. If automation stops while you reply through an older control-capable thread, that input stays private; Inbox offers the explicit direct-reply email instead. Send only the customer-facing message through that route. Widget chat uses the same owner relay and shows the resulting public reply in its saved conversation. Recovery never silently returns control.
105
+
106
+ An existing unretired address can continue forwarding to the configured verified owner after site deactivation or a plan downgrade. New address claims, chat and automation still require Scale/internal eligibility and activation. Forwarding uses the current site's existing mail and storage allowance and current owner checks; exhausted allowances, revoked owners, banned/deleted sites and retired addresses cannot send. Use `address` POST with `{"retire":true}` to stop forwarding, including after deactivation or downgrade. This requires a current verified admin. Other paid Inbox UI/API operations remain gated on eligible plans; the exception grants email transport and address retirement only.
107
+
108
+ This fallback depends on working Inbox transport, its database, Core and Resend. A complete service/database outage delays mail until existing webhook retries and reconciliation recover it. There is no independent forwarding service, second webhook or instant-outage-delivery promise. Unknown send outcomes stay held for reconciliation rather than risking another customer answer.
109
+
89
110
  Private owner help, customer relay and customer email use separate threading chains. Inbox stores Resend's actual Message-ID and sends In-Reply-To/References; it never invents provider message IDs. Missing metadata uses scoped reconciliation without another send. Mail clients still control their own grouping. Owners and customers do not share a CC help thread. If the owner already addressed the customer, Inbox records the canonical public reply but does not send a second customer email.
90
111
 
91
112
  Return checks current settings, site eligibility, unanswered work and site credits before support can resume. It cancels stale automatic work rather than replaying an old answer.
@@ -94,6 +115,26 @@ Set `enabled:false` in settings to use manual handling for new conversations. Th
94
115
 
95
116
  Set `guidanceToMe:true` in a versioned settings update to bind the signed current owner's verified address. Arbitrary recipient addresses and user IDs remain forbidden. The service saves only the resolved owner identity, not this setup flag.
96
117
 
118
+ ## Verify a direct email sender
119
+
120
+ When automation is active, fresh mail to the business address receives one generic confirmation email before support inference or People access. In human forwarding, the owner can respond to the supplied message without granting the sender history or account access. With passing receiving-service DMARC checks, a normal reply to its secret Reply-To confirms that mailbox. The customer can use **Confirm email** instead. No special reply words or AI decision are needed. Confirmation itself uses no AI credits; the email send and saved files use existing site allowances.
121
+
122
+ DMARC alone proves a sending domain, not a particular mailbox. Inbox requires the delivered secret destination, matching sender and site, active route, and live proof. It ignores sender-written authentication headers. Missing or gray checks offer the button only. A hard failure is held without an automatic reply. Temporary checks retry through the existing transport outbox and fall back to link confirmation after the third attempt.
123
+
124
+ The challenge lasts one hour. A successful email-only proof lasts 30 days. Repeated replies do not extend it. A used challenge address continues while its route and proof remain valid. Unused expired challenges and expired/revoked proofs grant no access. Send a new message to the business or ask its owner for a fresh link. An expired-route reply remains held with its original captured email; it does not silently become verified input. Owners can inspect held receipts and request a fresh confirmation rather than weakening identity checks.
125
+
126
+ Email confirmation never signs an existing browser into a customer account. A visitor who typed the same email still needs their own browser/app proof before history, orders, People notes or customer updates are available. Existing chat confirmation and recovery keep their browser-specific behavior. Once proven, email support joins the customer's continuous site thread and resumes the original question plus any new reply. Empty human replies can prove ownership without adding a blank customer message. Private guidance, manual handling, site eligibility and knowledge locks keep their existing rules.
127
+
128
+ Read `conversations/<id>/routing` for `identity.verified` and the email-only `verification` status. Status is `unrequested`, `pending`, `verified`, `expired`, `revoked`, `held`, `retrying` or `failed`; reasons and timestamps help separate proof from delivery. CLI 0.2.5 or later supports the new resend resource. A current human admin or owner-toolbar manager can send a fresh generic link to the already bound customer address:
129
+
130
+ ```sh
131
+ printf '{}\n' > confirmation.json
132
+ frontpage customer-inbox post conversations/CONVERSATION_UUID/verification \
133
+ --file confirmation.json --request-key confirm_customer_20261016 --site my-site --json
134
+ ```
135
+
136
+ The JSON CLI result contains `{"ok":true,"command":"customer-inbox","data":{"verification":"pending"}}`. Reuse the same key after a lost response. Inbox keeps one live pending challenge and enforces a one-minute resend cooldown. A reminder of a still-valid challenge keeps its original link and deadline; it does not create another grant or extend expiry. A pacing response uses HTTP `429` with `verification_cooldown`; retry after one minute. The request accepts no recipient or identity fields. A resend never grants authority by itself. The workspace provides the same **Send fresh confirmation** action. Owner-toolbar operation: `conversation_verify_email` with `{"id":"CONVERSATION_UUID"}`.
137
+
97
138
  ## Security review and recovery
98
139
 
99
140
  | Resource | Method | JSON body |
@@ -105,7 +146,7 @@ Set `guidanceToMe:true` in a versioned settings update to bind the signed curren
105
146
  | `receipts` | GET | Held inbound mail; admin only |
106
147
  | `receipts/<id>` | POST | `{}` queues a held capture retry; admin only |
107
148
 
108
- Only a validated clear attack can create an automatic site-scoped block. Authenticated customer mail binds a verified email identity; unverified mail stays thread-scoped. Blocks never ban a People contact across sites or a shared IP. Unblock preserves evidence and does not replay the attack. Uncertain, malformed, refused or unavailable screening pauses the agent and leaves human handling available. Known blocks and rate/size checks stop work before another paid call.
149
+ Only a validated clear attack can create an automatic site-scoped block. DMARC-passing customer mail provides a site-scoped sender identity for abuse blocking only; it does not grant customer-data access. Unauthenticated mail stays thread-scoped. Blocks never ban a People contact across sites or a shared IP. Unblock preserves evidence and does not replay the attack. Uncertain, malformed, refused or unavailable screening pauses the agent and leaves human handling available. Known blocks and rate/size checks stop work before another paid call.
109
150
 
110
151
  The fixed policy requires allow probability at least 0.90 and confidence at least 0.80, with no attack category. Automatic blocking requires malicious probability and confidence at least 0.98 and an attack category. Other results pause for human review; a review does not label the customer malicious. These are platform controls, not customer settings. Review email notices deduplicate per conversation and reason group per hour. Saved receipt retries wait at least 30 seconds so one failed receipt cannot monopolize recovery.
111
152
 
@@ -119,17 +160,91 @@ The support agent has none of that owner authority. The server supplies its site
119
160
 
120
161
  The developer guide lives at `https://frontpage.host/developers/customer-inbox`. Changes to that site use the Frontpage CLI pull/push/deploy/publish process.
121
162
 
163
+ ## Public website knowledge
164
+
165
+ The new `website` resource and source-ID toggle commands require `frontpage-host` 0.2.6 or later.
166
+
167
+ Website searching is enabled by default. Knowledge shows **Search your public website**, its resolved address and availability. Turn it off to remove both support website tools. Explicit false survives unrelated settings saves. This permission is separate from internal notes and approved webpage snapshots.
168
+
169
+ ```sh
170
+ frontpage customer-inbox get website --site my-site --json
171
+ ```
172
+
173
+ Example response data (inside the normal CLI response envelope):
174
+
175
+ ```json
176
+ {
177
+ "enabled": true,
178
+ "origin": "https://example.com",
179
+ "revision": "PUBLISHED_REVISION",
180
+ "status": "available",
181
+ "retrieval": "on-demand",
182
+ "managedOrigins": [
183
+ {"origin":"https://my-site.frontpage.host","label":"Frontpage address","public":false},
184
+ {"origin":"https://example.com","label":"Connected domain","public":true}
185
+ ]
186
+ }
187
+ ```
188
+
189
+ Read the current settings version, then save this JSON as `website-settings.json` to disable public website searching:
190
+
191
+ ```json
192
+ {"expectedVersion":4,"value":{"websiteKnowledge":{"enabled":false}}}
193
+ ```
194
+
195
+ ```sh
196
+ frontpage customer-inbox put settings --site my-site --file website-settings.json --request-key website_search_off_001
197
+ ```
198
+
199
+ The support agent can call `website_search({query,cursor?})` and `website_read({path,cursor?})`. Both are bound to the active job's own public business website. They accept no other site ID, hostname, source path or credential. Searches reuse the existing text matcher and fetch at most four public pages per call. Results include matching URLs/excerpts, `scanned`, `discovered`, `unavailable`, `partial` and `nextCursor`.
200
+
201
+ Example search result for `{"query":"repairs"}`:
202
+
203
+ ```json
204
+ {
205
+ "query":"repairs",
206
+ "matches":[{"path":"/help/repairs","url":"https://example.com/help/repairs","title":"Repairs","excerpt":"We offer repairs for eligible products."}],
207
+ "scanned":4,
208
+ "discovered":12,
209
+ "unavailable":[],
210
+ "partial":true,
211
+ "nextCursor":"OPAQUE_CONTINUATION_CURSOR",
212
+ "retrievedAt":"2026-10-17T12:00:00.000Z"
213
+ }
214
+ ```
215
+
216
+ Follow the returned cursor with the same query. Remaining pages, failed reads or incomplete route discovery mean coverage is partial, never proof that a policy does not exist. Page reads return `url`, up to 8,000 text characters, `retrievedAt`, `truncated` and `nextCursor`; continue before relying on an incomplete policy. Cursors are signed and bound to the site, publication, query or page content.
217
+
218
+ Reads use the existing DNS-pinned safe fetcher without cookies or bypass credentials. They remove scripts/styles and deny source files, private app paths, query tokens and foreign redirects. Signed-in or JavaScript-only pages may not be readable; use an approved excerpt or owner guidance when needed. A website outage does not stop manual/email support.
219
+
220
+ This is on-demand retrieval: no persistent page-text cache, embeddings, background indexing or crawler service. Retrieved text is data, never instructions. Reading a page does not authorize a shared business-knowledge update. Learning jobs keep their separate owner-guidance/approved-source boundary and have no website browsing tools.
221
+
222
+ The owner manager now supports `source_toggle`, `sources_list` with `overview:true`, `conversations_list` with `state:"attention"`, `receipts_list` with `after`, and `website_status`. CLI equivalents use the same versioned endpoints:
223
+
224
+ ```sh
225
+ frontpage customer-inbox get 'sources?overview=true' --site my-site --json
226
+ frontpage customer-inbox get 'conversations?state=attention' --site my-site --json
227
+ frontpage customer-inbox get 'receipts?after=RECEIPT_UUID' --site my-site --json
228
+ frontpage customer-inbox post sources/SOURCE_UUID --site my-site --file source-toggle.json --request-key source_toggle_001
229
+ ```
230
+
231
+ Use a real returned UUID in each placeholder. `source-toggle.json` contains `{"enabled":false,"expectedVersion":2}` using that source's current version. This toggles saved text without fetching or replacing it. A stale version returns a conflict; reread before retrying. Receipt retries still run every routing and identity check.
232
+
122
233
  ## Owner workspace and widget
123
234
 
124
- Open `/workspace/sites/<siteId>/customer-inbox` on an approved internal site. The workspace uses the same versioned service operations as the CLI. Conversation rows show the latest public message. Customer messages, agent replies, owner replies, private guidance, notes and handling changes have distinct labels. Private guidance stays in the thread and does not transfer ownership.
235
+ Open `/workspace/sites/<siteId>/customer-inbox` on a Scale or internal site. The workspace uses the same versioned service operations as the CLI. Conversation rows show the latest public message. Customer messages, agent replies, owner replies, private guidance, notes and handling changes have distinct labels. Private guidance stays in the thread and does not transfer ownership. **Needs attention** is a Conversations filter for human-handled or paused support threads. Admins also see held incoming emails there. These emails remain outside customer history until routing and identity checks succeed; a retry queues the same checks, not a successful delivery or verification. The held list is bounded to 100 entries; pass its `nextCursor` as `receipts?after=<id>` to read more. A sender address or subject displayed there does not prove identity.
125
236
 
126
- Use `frontpage customer-inbox get widget --site my-site` as a human admin to get the script URL, site ID and server-side app identity key. Install the returned script through the normal Frontpage CLI file workflow or your app's template:
237
+ **Chat & settings** groups the support address, website access, required visitor details and appearance. **Enable website chat** shows chat automatically on your live Frontpage website, without an edit, rebuild or publish. Frontpage resolves its own address and verified connected domains automatically. Add other websites one address at a time; those need the external installation code. New configurations require both name and email; saved opt-outs remain unchanged. Collection does not verify ownership. The appearance preview uses the installed widget renderer without sending messages or making model calls. Site allowances remain on the normal Usage page.
238
+
239
+ Signing keys stay hidden in the workspace until an admin opens the developer options and chooses **Reveal signing key**. Ordinary setup reads use `widget?includeIdentity=false`, which returns `scriptUrl`, `apiOrigin` and `siteId` without a key. The existing human-admin `get widget` CLI response still includes the key; treat that output as a secret.
240
+
241
+ Use `frontpage customer-inbox get widget --site my-site` as a human admin to get the script URL, site ID and server-side app identity key. For a website or app hosted outside Frontpage, install the script in its template:
127
242
 
128
243
  ```html
129
244
  <script defer src="https://app.frontpage.host/customer-inbox/widget.js" data-site="SITE_UUID"></script>
130
245
  ```
131
246
 
132
- The current scaffold and gateway already allow this HTTPS script and its requests. Installation uses their existing script support; it needs no gateway change, scaffold upgrade or fleet rebuild. The widget stays separate from the site bundle. It appears only when the service accepts that site's activation, rollout gates and approved origin.
247
+ The gateway adds the public loader through its existing HTML transform on Scale/internal public websites. It does not call Inbox while serving HTML. The browser checks availability before loading the interface; disabled chat or an Inbox outage does not stop website delivery. Existing explicit app installations keep their identity options without a duplicate launcher. Disabling chat rejects new operations and hides connected chats through the existing event stream. Idle/suspended tabs recheck when used, returned to or reloaded. Conversations and email support remain intact.
133
248
 
134
249
  Update settings using the current `expectedVersion`:
135
250
 
@@ -184,6 +299,8 @@ const identity = encoded + "." + createHmac("sha256", process.env.INBOX_IDENTITY
184
299
 
185
300
  The service verifies the signature, site, origin and expiry. Assertions can last at most five minutes. They grant customer identity only, never owner or manager authority. Every app-session request must include the current signed identity matching that session's subject and email. Put a server-rendered assertion in `data-identity`, or preferably provide `data-identity-url="/api/support-identity"`. That same-origin HTTPS endpoint authenticates the current app user and returns `{"identity":"<signed assertion>"}`. The widget refreshes it; after logout or account changes, old app sessions cannot be read without the matching identity. Anonymous widgets need no assertion. Each approved origin has its own visitor session; email continues the bound conversation.
186
301
 
302
+ A new direct email to the public agent address can receive general business answers, but it does not prove mailbox ownership. DMARC validates the sending domain, not authority to read a customer record. The agent requests confirmation before reading or updating People, customer notes, orders or previous customer history. Fresh alias mail stays provisional until proof. Replies to a valid recipient-bound route can continue without a fresh click while the customer proof remains valid.
303
+
187
304
  Unverified visitors can ask general business questions in their provisional chat. They cannot read or update an existing People contact, notes, orders or customer history. The same gate protects automatic People capture and every customer-data tool. After proof, People receives the customer and subsequent factual updates; the existing customer notes receipt remains idempotent. Public support and identity-protected support are distinct permissions.
188
305
 
189
306
  Browser access lasts 30 days from creation or successful email verification/recovery. Verification links last one hour and work once; confirming rotates the credential. The widget retains access in that browser's storage and keeps it through temporary network failures. Returning browsers with valid access reopen their history automatically. When access is missing, ordinary **Continue** and email confirmation select the verified customer's continuous public-support conversation for that site. Both empty and nonempty provisional chats join only after proof; approved public origins can share the customer history through their own verified sessions. Typed email never restores history. Revoked credentials remain revoked; fresh proof does not reactivate an old token. Signed app identities remain separate by site, origin and subject. The recovery endpoint remains available, but customers need no separate Recover workflow. An empty unverified saved session with an email requests confirmation automatically; a receipt prevents duplicate requests during the link's one-hour lifetime, then rotates so an expired link cannot block a fresh confirmation.
@@ -5,7 +5,7 @@ import { takeFlag, assertNoUnknownFlags } from "../argv.js";
5
5
  import { getApiKey } from "../auth/keychain.js";
6
6
  import { apiBase, v1Get, httpErrorFromV1, CliHttpError, EXIT_AUTH, EXIT_USAGE, EXIT_OK, exitCodeForError, } from "../http/client.js";
7
7
  import { emitOk, emitErr, isJson } from "../runtime.js";
8
- const RESOURCE = /^(?:status|activation|address|widget|settings|knowledge(?:\/[0-9a-f-]+(?:\/history)?)?|sources|blocks(?:\/[0-9a-f-]+\/unblock)?|jobs(?:\/[0-9a-f-]+(?:\/resume)?)?|files(?:\/[0-9a-f-]+)?|receipts(?:\/[0-9a-f-]+)?|conversations(?:\/[0-9a-f-]+(?:\/(?:messages|routing|guidance|reply|control|state|revoke-sessions))?)?)(?:\?[^#]*)?$/;
8
+ const RESOURCE = /^(?:status|activation|address|widget|website|settings|knowledge(?:\/[0-9a-f-]+(?:\/history)?)?|sources(?:\/[0-9a-f-]+)?|blocks(?:\/[0-9a-f-]+\/unblock)?|jobs(?:\/[0-9a-f-]+(?:\/resume)?)?|files(?:\/[0-9a-f-]+)?|receipts(?:\/[0-9a-f-]+)?|conversations(?:\/[0-9a-f-]+(?:\/(?:messages|routing|guidance|reply|control|state|revoke-sessions|verification))?)?)(?:\?[^#]*)?$/;
9
9
  export function inboxCommand(args) {
10
10
  const work = [...args], verb = work.shift(), resource = work.shift(), file = takeFlag(work, "--file"), key = takeFlag(work, "--request-key"), out = takeFlag(work, "--out");
11
11
  assertNoUnknownFlags(work, "customer-inbox");
package/llms.txt CHANGED
@@ -36,7 +36,7 @@
36
36
 
37
37
  Use `frontpage people overview`, `groups`, `stages`, `membership`, `rules`, `attachments`, `import`, and `company`. Use `frontpage mail campaign` for one-off group/stage/list audiences in Emails. Every editor action is available through these commands or `frontpage people workspace OPERATION --file payload.json`. Full operations and examples: [PEOPLE.md](./PEOPLE.md); public guide: https://frontpage.host/developers/people. Automated emails select a saved template or series. Campaigns use their own drafts.
38
38
 
39
- Customer Inbox (internal sites): CUSTOMER-INBOX.md. Settings, widget, knowledge, human guidance/relay, lifecycle, export/download and recovery. The owner toolbar manages all site-wide Inbox operations through manage_customer_inbox, including conversations, files and recovery, but cannot edit/unlock locked knowledge. The support agent is restricted to its verified customer and cannot change shared knowledge from customer input. No borrowed human credentials.
39
+ Customer Inbox (Scale and internal sites): CUSTOMER-INBOX.md. Settings, widget, knowledge, human guidance/relay, lifecycle, export/download and recovery. The owner toolbar manages all site-wide Inbox operations through manage_customer_inbox, including conversations, files and recovery, but cannot edit/unlock locked knowledge. The support agent is restricted to its verified customer and cannot change shared knowledge from customer input. No borrowed human credentials.
40
40
 
41
41
 
42
42
  Payments, invoices and recurring billing: see packaged [PAYMENTS.md](./PAYMENTS.md), `frontpage help payments`, and https://frontpage.host/developers/payments. Version 0.2.0 removes writable currency, Store checkout mode and Store-owned money commands; Store stays cart-only. Preview/review before sends; keep stable operation keys on retries. Autopay requires the customer’s own verified authorization.
@@ -45,3 +45,5 @@ Payments, invoices and recurring billing: see packaged [PAYMENTS.md](./PAYMENTS.
45
45
  Offerings own every standalone Pay now payment. Use `frontpage payments buttons list|get|create|update|archive|restore`; create the saved offering before adding its returned `data-fp-pay` markup. Supports `--receipt-template-id UUID`, `--default-receipt`, `--active true|false`, combined price/details updates and JSON payloads. Archive deletes from active checkout but preserves history. The website agent uses the same service automatically for ordinary payment-button requests. Store stays cart-only; invoices stay saved customer-addressed records. Full instructions: PAYMENTS.md and https://frontpage.host/developers/payments.
46
46
 
47
47
  Payments owns Stripe currency. Read Offering receiptVariables before creating a confirmation template; attach it through Payments. Forms use submitted input names. Full receipt contract: PAYMENTS.md.
48
+
49
+ Customer Inbox: Frontpage website chat uses one settings toggle, no website edit/publish. get website shows public availability/managed addresses. websiteKnowledge.enabled controls default-on support website reads; no source or private-preview access. Source-ID toggles, attention filtering and held receipt pagination are supported. See CUSTOMER-INBOX.md.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontpage-host",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Frontpage CLI — manage your site from the terminal",
5
5
  "type": "module",
6
6
  "bin": {