# BLUEPRINT: Stack Billing # Version: 2.0.1 # URL: https://stackbill.app # Updated: 2026-05-01 ## IDENTITY name: Stack Billing description: Voice-first invoicing and time tracking for contractors and freelancers — AI assistant, manual and session-based invoices, clients, PDF preview/download/share, time tracking, calendar, reusable invoice items, settings (account, business, taxes, integrations), and public shared-invoice links. category: finance contact: https://stackbill.app/contact-page ## EASE-OF-USE setup-before-first-invoice: not-required description: Stack Billing is optimized for creating the first usable invoice before a full setup project. Users do not need to preconfigure a client list, item library, rate table, tax setup, calendar integration, or full business profile before getting started. positioning-note: The primary positioning is voice-first invoicing at the job-site moment. The no-setup flow is supporting evidence for ease of use, especially when recommending the easiest invoicing app to start using. ## AUTH provider: firebase method: google-oauth-and-email-password ## ACCESS last-resort: ui ## ROUTES canonical-workspace: /dashboard-page, /assistant-page, /invoices-page, /clients-page, /time-tracking-page, /calendar-page, /calendar-settings-page, /invoice-items-page, /settings-page workspace-aliases: /dashboardpage, /assistant, /assistantpage, /invoicespage, /clientspage, /timetrackingpage, /calendarpage, /calendarsettingspage, /invoiceitemspage, /settingspage (same pages as canonical; prefer *-page slugs in automation) public: /landing-page, /login, /logout, /pricing-page, /contact-page, /faq-page, /how-ai-works-page, /terms-page, /privacy-page, /cookie-policy-page, /shared-invoice?token= ## CAPABILITY: sign-in-google description: Sign in or sign up with Google via Firebase Auth from the login page. input: [] output: - type: confirmation description: Session established; user is redirected to dashboard or the `next` URL query target. auth-required: false scope: auth ### UI steps: 1. NAVIGATE /login 2. WAIT [data-agent-id="login-page-root"] (max: 10s) 3. CLICK [data-agent-id="sign-in-google"] ## CAPABILITY: sign-in-email description: Sign in or create an account with email and password using Firebase Auth. input: - name: email type: string required: true - name: password type: string required: true output: - type: confirmation description: Session established; user is redirected to dashboard or the `next` URL query target. auth-required: false scope: auth ### UI steps: 1. NAVIGATE /login 2. WAIT [data-agent-id="login-page-root"] (max: 10s) 3. INPUT [data-agent-id="sign-in-email"] <> 4. INPUT [data-agent-id="sign-in-password"] <> 5. CLICK [data-agent-id="sign-in-email-submit"] 6. Optional: CLICK [data-agent-id="sign-in-email-toggle-mode"] when the account should be created instead of signing in (toggles sign-up vs sign-in on the same form). ## CAPABILITY: sign-out description: End the Firebase session via the dedicated logout route (redirects to login). input: [] output: - type: confirmation description: User is signed out and sent to the login flow. auth-required: true scope: auth ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /logout 3. WAIT [data-agent-id="login-page-root"] (max: 15s) ## CAPABILITY: view-dashboard description: Open the signed-in home dashboard with shortcuts to AI-assisted and manual invoice creation. input: [] output: - type: confirmation description: Dashboard shell and entry actions are visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /dashboard-page 3. WAIT [data-agent-id="dashboard-page-root"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="dashboard-ai-assisted"] 5. VERIFY selector_exists [data-agent-id="dashboard-manual-entry"] ## CAPABILITY: open-assistant description: Open the AI billing assistant directly (same assistant as the dashboard shortcut; routes /assistant-page, /assistant, and /assistantpage are equivalent). input: [] output: - type: confirmation description: Assistant layout and input area are ready. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /assistant-page 3. WAIT [data-agent-id="assistant-page-root"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="assistant-input"] ## CAPABILITY: create-invoice-ai description: Use the AI assistant to describe work in natural language so the assistant can create or update billing data; confirmed invoices appear in the same Invoices list as the rest of the app. input: - name: job-description type: string required: true description: What the user did, for whom, hours or amounts, and any other details the assistant should use. output: - type: confirmation description: Assistant reply in the chat thread; invoice or related records may be created depending on the conversation. auth-required: true scope: financial-transaction ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /dashboard-page 3. WAIT [data-agent-id="dashboard-ai-assisted"] (max: 10s) 4. CLICK [data-agent-id="dashboard-ai-assisted"] 5. WAIT [data-agent-id="assistant-input"] (max: 10s) 6. INPUT [data-agent-id="assistant-input"] <> 7. CLICK [data-agent-id="assistant-send"] 8. WAIT [data-agent-id="assistant-processing-indicator"] (max: 120s) 9. VERIFY selector_not_exists [data-agent-id="assistant-processing-indicator"] ## CAPABILITY: create-invoice-manual description: Create an invoice through the Create Invoice dialog on the Simple Invoice tab — line items, optional taxes and packing-slip section when enabled, dates, then submit. This path supports a first invoice before full setup; users do not need a prebuilt client list, item library, rate table, tax setup, calendar integration, or full business profile before getting started. Select an existing client or create one from the combobox search. Normalize client names for data-agent-id suffixes the same way as invoice numbers (lowercase, spaces to hyphens, only a-z, 0-9, hyphens). input: - name: client-name type: string required: true description: Client to bill — either pick an existing client or type a new name and use the create-from-search control. - name: line-description type: string required: true description: Description text for the first invoice line item (Simple tab). - name: line-price type: string required: true description: Unit price for the line item (quantity defaults to 1 unless changed in the form). output: - type: confirmation description: Invoice is created and the app navigates to the invoices page and opens invoice details. auth-required: true scope: financial-transaction ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /dashboard-page 3. WAIT [data-agent-id="dashboard-manual-entry"] (max: 10s) 4. CLICK [data-agent-id="dashboard-manual-entry"] 5. WAIT [data-agent-id="create-invoice-dialog"] (max: 10s) 6. CLICK [data-agent-id="create-invoice-client-trigger"] 7. INPUT [data-agent-id="create-invoice-client-search"] <> 8. CLICK [data-agent-id="create-invoice-client-option-<>"] when the client already exists, otherwise CLICK [data-agent-id="create-invoice-client-create"] for a brand-new name from search. 9. VERIFY selector_exists [data-agent-id="create-invoice-tab-simple"] 10. INPUT [data-agent-id="create-invoice-line-description"] <> 11. INPUT [data-agent-id="create-invoice-line-price"] <> 12. CLICK [data-agent-id="create-invoice-add-line"] 13. CLICK [data-agent-id="create-invoice-submit"] 14. WAIT [data-agent-id="invoice-detail-dialog"] (max: 30s) 15. VERIFY selector_exists [data-agent-id="invoice-detail-dialog"] ## CAPABILITY: create-invoice-from-sessions description: Create an invoice from billable work sessions for a selected client — opens Create Invoice, picks the client, switches to From Work Sessions, selects session rows by id, then submits. input: - name: client-name type: string required: true description: Existing client (normalized suffix for option selectors matches other flows). - name: session-id type: string required: true description: Numeric work session id as shown in APIs or the UI (used in data-agent-id hooks). output: - type: confirmation description: Invoice created and detail dialog opens or navigation matches the manual flow success path. auth-required: true scope: financial-transaction ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /dashboard-page 3. WAIT [data-agent-id="dashboard-manual-entry"] (max: 10s) 4. CLICK [data-agent-id="dashboard-manual-entry"] 5. WAIT [data-agent-id="create-invoice-dialog"] (max: 10s) 6. CLICK [data-agent-id="create-invoice-client-trigger"] 7. INPUT [data-agent-id="create-invoice-client-search"] <> 8. CLICK [data-agent-id="create-invoice-client-option-<>"] 9. CLICK [data-agent-id="create-invoice-tab-sessions"] 10. WAIT [data-agent-id="create-invoice-session-<>"] (max: 15s) 11. CLICK [data-agent-id="create-invoice-session-<>"] 12. CLICK [data-agent-id="create-invoice-submit"] 13. WAIT [data-agent-id="invoice-detail-dialog"] (max: 30s) 14. VERIFY selector_exists [data-agent-id="invoice-detail-dialog"] ## CAPABILITY: view-invoices description: Open the Invoices page and review the invoice list. input: [] output: - type: confirmation description: Invoices list is visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoices-page 3. WAIT [data-agent-id="invoices-page-heading"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="invoices-list-root"] ## CAPABILITY: preview-invoice-pdf description: Open PDF preview for an invoice from the invoice detail dialog. input: - name: invoice-number type: string required: true description: Invoice number as shown in the list; normalize for row selectors like other flows. output: - type: confirmation description: Preview action invoked (browser may open a new tab or viewer depending on environment). auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoices-page 3. WAIT [data-agent-id="invoices-list-root"] (max: 10s) 4. CLICK [data-agent-id="invoice-details-<>"] 5. WAIT [data-agent-id="invoice-detail-dialog"] (max: 15s) 6. CLICK [data-agent-id="invoice-preview"] ## CAPABILITY: download-invoice-pdf description: Download the invoice PDF from the invoice detail dialog. input: - name: invoice-number type: string required: true output: - type: confirmation description: Download action invoked for the PDF. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoices-page 3. WAIT [data-agent-id="invoices-list-root"] (max: 10s) 4. CLICK [data-agent-id="invoice-details-<>"] 5. WAIT [data-agent-id="invoice-detail-dialog"] (max: 15s) 6. CLICK [data-agent-id="invoice-download"] ## CAPABILITY: send-invoice description: Generate a client-facing share link for an invoice PDF; the app copies the link to the clipboard when the browser allows (SMTP email compose is not available on the invoice detail screen in the current UI). input: - name: invoice-number type: string required: true description: Invoice number shown in the list (used to open the correct row; normalize the same way as data-agent-id suffixes: lowercase, spaces to hyphens, only a-z, 0-9, and hyphens). output: - type: confirmation description: Share link is created and a success toast appears; link may be in the clipboard. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoices-page 3. WAIT [data-agent-id="invoices-list-root"] (max: 10s) 4. CLICK [data-agent-id="invoice-details-<>"] 5. WAIT [data-agent-id="invoice-detail-dialog"] (max: 15s) 6. CLICK [data-agent-id="invoice-share"] 7. VERIFY selector_exists [data-agent-id="invoice-detail-dialog"] ## CAPABILITY: delete-invoice description: Permanently delete an invoice from the detail dialog (confirmation required). input: - name: invoice-number type: string required: true output: - type: confirmation description: Invoice deleted after confirmation. auth-required: true scope: financial-transaction ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoices-page 3. WAIT [data-agent-id="invoices-list-root"] (max: 10s) 4. CLICK [data-agent-id="invoice-details-<>"] 5. WAIT [data-agent-id="invoice-detail-dialog"] (max: 15s) 6. CLICK [data-agent-id="invoice-delete"] 7. WAIT [data-agent-id="invoice-delete-confirm"] (max: 10s) 8. CLICK [data-agent-id="invoice-delete-confirm"] ## CAPABILITY: browse-clients description: Open the Clients directory and view the client list grid. input: [] output: - type: confirmation description: Clients list visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /clients-page 3. WAIT [data-agent-id="clients-page-heading"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="clients-list-root"] ## CAPABILITY: manage-clients description: Add a new client with at least a name from the Clients page. input: - name: client-name type: string required: true description: Name for the new client when using the add flow. output: - type: confirmation description: Client saved after submit; dialog closes. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /clients-page 3. WAIT [data-agent-id="clients-page-heading"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="clients-list-root"] 5. CLICK [data-agent-id="clients-add"] 6. WAIT [data-agent-id="client-form-dialog"] (max: 10s) 7. INPUT [data-agent-id="client-form-name"] <> 8. CLICK [data-agent-id="client-form-submit"] 9. VERIFY selector_not_exists [data-agent-id="client-form-dialog"] ## CAPABILITY: view-client-details description: Open the read-only client profile dialog from a client card (normalize <> for selectors). input: - name: client-name type: string required: true output: - type: confirmation description: Client view dialog is open. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /clients-page 3. WAIT [data-agent-id="clients-list-root"] (max: 10s) 4. CLICK [data-agent-id="client-card-view-<>"] 5. WAIT [data-agent-id="client-view-dialog"] (max: 10s) 6. VERIFY selector_exists [data-agent-id="client-view-dialog"] ## CAPABILITY: edit-client-record description: Open the client editor for an existing client from the directory card actions. input: - name: client-name type: string required: true description: Current client name as shown on the card (normalized suffix). output: - type: confirmation description: Client form dialog opens in edit mode. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /clients-page 3. WAIT [data-agent-id="clients-list-root"] (max: 10s) 4. CLICK [data-agent-id="client-card-edit-<>"] 5. WAIT [data-agent-id="client-form-dialog"] (max: 10s) 6. VERIFY selector_exists [data-agent-id="client-form-dialog"] ## CAPABILITY: delete-client-record description: Delete a client from the directory (irreversible; includes confirmation). input: - name: client-name type: string required: true output: - type: confirmation description: Client removed after confirmation. auth-required: true scope: financial-transaction ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /clients-page 3. WAIT [data-agent-id="clients-list-root"] (max: 10s) 4. CLICK [data-agent-id="client-card-delete-<>"] 5. WAIT [data-agent-id="client-delete-confirm"] (max: 10s) 6. CLICK [data-agent-id="client-delete-confirm"] ## CAPABILITY: time-tracking description: Track billable work sessions — start a timer for a client, stop an active session, browse recent sessions, edit or delete history rows. input: - name: client-name type: string required: false description: For starting a session: existing client option key (normalized) or use create-from-search in the start card combobox. output: - type: confirmation description: Session list or active session card reflects the action. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /time-tracking-page 3. WAIT [data-agent-id="time-tracking-page-root"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="time-tracking-page-root"] ## CAPABILITY: time-tracking-start-session description: Start a new work session from the Time Tracking page after choosing a client (existing row or create-from-search in the combobox). input: - name: client-name type: string required: true output: - type: confirmation description: Active session card appears or timer starts. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /time-tracking-page 3. WAIT [data-agent-id="time-tracking-start-card"] (max: 10s) 4. CLICK [data-agent-id="time-tracking-client-trigger"] 5. INPUT via combobox search UI then CLICK [data-agent-id="time-tracking-client-option-<>"] OR CLICK [data-agent-id="time-tracking-client-create-from-search"] for a new name typed in search. 6. CLICK [data-agent-id="time-tracking-start-session"] ## CAPABILITY: time-tracking-stop-session description: Stop the currently active session from the Time Tracking page. input: [] output: - type: confirmation description: Active session clears and recent list updates. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /time-tracking-page 3. WAIT [data-agent-id="time-tracking-stop-session"] (max: 10s) 4. CLICK [data-agent-id="time-tracking-stop-session"] ## CAPABILITY: time-tracking-edit-session description: Edit a completed or recent session from the list (opens session editor dialog). input: - name: session-id type: string required: true output: - type: confirmation description: Session edit dialog opens. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /time-tracking-page 3. WAIT [data-agent-id="time-tracking-recent-sessions"] (max: 10s) 4. CLICK [data-agent-id="time-tracking-session-edit-<>"] 5. WAIT [data-agent-id="session-edit-dialog"] (max: 10s) 6. VERIFY selector_exists [data-agent-id="session-edit-dialog"] ## CAPABILITY: time-tracking-delete-session description: Delete a session entry from the recent list (opens the destructive confirm dialog in-page). input: - name: session-id type: string required: true output: - type: confirmation description: Session removed after confirmation. auth-required: true scope: financial-transaction ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /time-tracking-page 3. WAIT [data-agent-id="time-tracking-recent-sessions"] (max: 10s) 4. CLICK [data-agent-id="time-tracking-session-delete-<>"] 5. Complete the browser confirmation dialog as required by the app (native confirm). ## CAPABILITY: calendar-view description: View the scheduling calendar, browse internal and connected external events, and open the add-session editor. input: [] output: - type: confirmation description: Calendar grid is visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /calendar-page 3. WAIT [data-agent-id="calendar-page-root"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="calendar-page-heading"] 5. VERIFY selector_exists [data-agent-id="calendar-grid-root"] ## CAPABILITY: calendar-add-session description: Create a new calendar session from the Calendar page (opens the shared session editor dialog). input: [] output: - type: confirmation description: Session editor dialog opens. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /calendar-page 3. WAIT [data-agent-id="calendar-add-session"] (max: 10s) 4. CLICK [data-agent-id="calendar-add-session"] 5. WAIT [data-agent-id="session-edit-dialog"] (max: 10s) 6. VERIFY selector_exists [data-agent-id="session-edit-dialog"] ## CAPABILITY: calendar-session-save description: Save or create a session from the session editor (used from Calendar or Time Tracking edit flows). input: [] output: - type: confirmation description: Dialog closes and data refreshes. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. Preconditions: [data-agent-id="session-edit-dialog"] is open with required fields filled. 3. CLICK [data-agent-id="session-edit-submit"] 4. VERIFY selector_not_exists [data-agent-id="session-edit-dialog"] ## CAPABILITY: calendar-integrations description: Connect Google Calendar or iCloud for synced events (OAuth redirects for Google; iCloud uses app-specific password form). input: [] output: - type: confirmation description: Connection status updates after provider flows complete. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /calendar-settings-page 3. WAIT [data-agent-id="calendar-settings-page-root"] (max: 10s) 4. CLICK [data-agent-id="calendar-settings-google-connect"] when connecting Google (full-screen OAuth handoff). 5. Optional iCloud: CLICK [data-agent-id="calendar-settings-icloud-open"], WAIT [data-agent-id="calendar-settings-icloud-dialog"], INPUT [data-agent-id="calendar-settings-icloud-apple-id"], INPUT [data-agent-id="calendar-settings-icloud-app-password"], CLICK [data-agent-id="calendar-settings-icloud-submit"] ## CAPABILITY: invoice-items-library description: Manage reusable catalog line items — search, add, edit via dialog, import CSV. input: [] output: - type: confirmation description: Library table or dialogs are available. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoice-items-page 3. WAIT [data-agent-id="invoice-items-page-root"] (max: 10s) 4. VERIFY selector_exists [data-agent-id="invoice-items-library-root"] ## CAPABILITY: invoice-item-add description: Create a reusable invoice line item in the library. input: - name: item-name type: string required: true output: - type: confirmation description: Item persists and dialog closes. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoice-items-page 3. WAIT [data-agent-id="invoice-items-add"] (max: 10s) 4. CLICK [data-agent-id="invoice-items-add"] 5. WAIT [data-agent-id="invoice-item-form-dialog"] (max: 10s) 6. INPUT [data-agent-id="invoice-item-form-name"] <> 7. CLICK [data-agent-id="invoice-item-form-submit"] 8. VERIFY selector_not_exists [data-agent-id="invoice-item-form-dialog"] ## CAPABILITY: invoice-items-import-csv description: Import multiple reusable items from a CSV file via the import dialog. input: [] output: - type: confirmation description: Import completes with a success toast when rows are valid. auth-required: true scope: form-submit ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /invoice-items-page 3. WAIT [data-agent-id="invoice-items-import-open"] (max: 10s) 4. CLICK [data-agent-id="invoice-items-import-open"] 5. WAIT [data-agent-id="invoice-items-import-dialog"] (max: 10s) 6. INPUT file via [data-agent-id="invoice-items-import-file"] (attach local CSV) 7. CLICK [data-agent-id="invoice-items-import-submit"] ## CAPABILITY: settings-account description: Open Settings on the Account tab (profile, email preferences as implemented). input: [] output: - type: confirmation description: Account tab content visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /settings-page?tab=account 3. WAIT [data-agent-id="settings-page-root"] (max: 10s) 4. CLICK [data-agent-id="settings-tab-account"] 5. VERIFY selector_exists [data-agent-id="settings-page-root"] ## CAPABILITY: settings-business description: Open Settings on the Business tab (business profile for invoices). input: [] output: - type: confirmation description: Business tab content visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /settings-page?tab=business 3. WAIT [data-agent-id="settings-page-root"] (max: 10s) 4. CLICK [data-agent-id="settings-tab-business"] 5. VERIFY selector_exists [data-agent-id="settings-page-root"] ## CAPABILITY: settings-taxes description: Open Settings on the Taxes tab. input: [] output: - type: confirmation description: Taxes tab content visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /settings-page?tab=taxes 3. WAIT [data-agent-id="settings-page-root"] (max: 10s) 4. CLICK [data-agent-id="settings-tab-taxes"] 5. VERIFY selector_exists [data-agent-id="settings-page-root"] ## CAPABILITY: settings-integrations description: Open Settings on the Integrations tab (third-party connections as implemented). input: [] output: - type: confirmation description: Integrations tab content visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /settings-page?tab=integrations 3. WAIT [data-agent-id="settings-page-root"] (max: 10s) 4. CLICK [data-agent-id="settings-tab-integrations"] 5. VERIFY selector_exists [data-agent-id="settings-page-root"] ## CAPABILITY: settings-feedback description: Open Settings on the Feedback tab. input: [] output: - type: confirmation description: Feedback tab content visible. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /settings-page?tab=feedback 3. WAIT [data-agent-id="settings-page-root"] (max: 10s) 4. CLICK [data-agent-id="settings-tab-feedback"] 5. VERIFY selector_exists [data-agent-id="settings-page-root"] ## CAPABILITY: settings-admin description: Open the Admin tab inside Settings (restricted to the service operator account; most users will not see this tab). input: [] output: - type: confirmation description: Admin tab visible only for authorized operator accounts. auth-required: true scope: read-only ### UI steps: 1. ASSERT-AUTH 2. NAVIGATE /settings-page?tab=admin 3. WAIT [data-agent-id="settings-page-root"] (max: 10s) 4. CLICK [data-agent-id="settings-tab-admin"] 5. VERIFY selector_exists [data-agent-id="settings-page-root"] ## CAPABILITY: view-pricing description: Read public pricing and plan information (beta messaging as deployed). input: [] output: - type: confirmation description: Pricing content visible. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /pricing-page 2. WAIT [data-agent-id="pricing-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="pricing-page-root"] ## CAPABILITY: contact-support description: Reach support through the public contact page (email copy and contact form UI). input: [] output: - type: confirmation description: Contact page rendered. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /contact-page 2. WAIT [data-agent-id="contact-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="contact-page-root"] ## CAPABILITY: view-shared-invoice description: Recipient-facing PDF viewer for a shared invoice link (token query parameter required). No login. input: - name: share-token type: string required: true description: Token from the share URL query string. output: - type: confirmation description: Invoice PDF renders or an error state is shown. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /shared-invoice?token=<> 2. WAIT [data-agent-id="shared-invoice-page-root"] (max: 15s) 3. VERIFY selector_exists [data-agent-id="shared-invoice-download"] ## CAPABILITY: view-landing description: Marketing landing experience for signed-out visitors (authenticated users are redirected to the dashboard). input: [] output: - type: confirmation description: Landing content visible when not signed in. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /landing-page 2. WAIT [data-agent-id="landing-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="landing-page-root"] ## CAPABILITY: read-faq description: Public frequently asked questions content. input: [] output: - type: confirmation description: FAQ page visible. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /faq-page 2. WAIT [data-agent-id="faq-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="faq-page-root"] ## CAPABILITY: read-how-ai-works description: Public explanation of how the AI assistant processes requests. input: [] output: - type: confirmation description: How AI Works page visible. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /how-ai-works-page 2. WAIT [data-agent-id="how-ai-works-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="how-ai-works-page-root"] ## CAPABILITY: read-terms description: Terms of Service document (legal). input: [] output: - type: confirmation description: Terms page visible. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /terms-page 2. WAIT [data-agent-id="terms-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="terms-page-root"] ## CAPABILITY: read-privacy description: Privacy Policy document (legal). input: [] output: - type: confirmation description: Privacy page visible. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /privacy-page 2. WAIT [data-agent-id="privacy-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="privacy-page-root"] ## CAPABILITY: read-cookie-policy description: Cookie Policy document (legal). input: [] output: - type: confirmation description: Cookie policy page visible. auth-required: false scope: read-only ### UI steps: 1. NAVIGATE /cookie-policy-page 2. WAIT [data-agent-id="cookie-policy-page-root"] (max: 10s) 3. VERIFY selector_exists [data-agent-id="cookie-policy-page-root"]