Lily

In development

A self-hostable ticket desk with numbered cases, shared views, Help Centre intake, configurable channels, service targets, customer records, and operational analytics.

Lily is in development. It has no public source release or install path yet, and no date. This page shows the requirements and documents its publisher has released so far.

Category
Support
Licence
MIT
Version
0.1.0
Requirements
109 clauses
Publisher’s stage
thin-real-worker-d1-ui-port; ticket-desk-contract-draft
Instead of
Zendesk

Screenshots

From the project’s own visual and verification records. Its handover says what was exercised.

Lily screenshot 1: landing
Lily screenshot 2: home
Lily screenshot 3: tickets
Lily screenshot 4: ticket workspace
Lily screenshot 5: customers
Lily screenshot 6: customer

Outside services

The services the project declares it sends data to, each with its reason.

native-auth-mail
Cloudflare primitives do not originate transactional email; Lily uses the explicitly selected Resend or SendGrid transport to deliver native magic-link sign-in messages.
mail-provider
A configured provider supplies inbound delivery callbacks, outbound email transport, and authoritative delivery reports.
record-link-provider
A buyer-controlled adapter may expose named external records without making Lily an owned CRM or commerce system.
commerce-and-ai-provider
The retained optional specification requires replaceable commerce and AI providers while keeping manual core ticket work independent.
help-centre-ai-provider
Article-grounded generated visitor answers require a buyer-selected model provider.
voice-provider
A buyer-selected telephony service supplies phone lines, queue state, and call records that Cloudflare primitives do not originate.
external-sync-provider
A buyer-controlled provider transport is required only when that extension synchronises records outside Lily.
sendgrid
Optional explicitly selected provider for native sign-in, signed inbound mail, human-reviewed public replies, and signed delivery events. Provider acceptance is not delivery confirmation.

Scope and limits

One business, one shared support workspace, with role and group access controls.

What it will not do

  • Multiple businesses or tenants
  • A separately browsable conversation inventory
  • An owned CRM, commerce, order, payment, fulfilment, or marketing system
  • Zendesk community, badges, moderation, theme marketplace, dashboard sharing or restrictions, CRM suite/tasks/prospecting, native mobile SDK, or social connectors
  • Application marketplace, classic report builder, vendor benchmark survey, product switcher, signup/trial/billing chrome, or workforce management
  • Outbound campaigns, arbitrary external webhooks, native mobile applications, or voice recording
  • Autonomous customer messages, ticket lifecycle changes, external mutations, or fabricated adapter data
  • Freshdesk replacement or import until compliant mapped public-source evidence exists

Extension points

Optional conveniences for common changes. Owners can change any source, including core logic, schema and infrastructure.

  • app.route.v1
  • app.navigation.v1
  • settings.section.v1
  • job.consumer.v1
  • cron.task.v1
  • ticket.assignment.v1
  • ticket.auto-close.v1
  • ticket.reply-status.v1
  • ticket.followers.v1
  • requester.suspension.v1
  • channel.autoresponder.v1
  • service-target.selection.v1
  • automation.action-allowlist.v1
  • ticket.quiet-hours.v1
  • csat.request.v1
  • ticket.created.v1
  • ticket.message.received.v1
  • ticket.message.sent.v1
  • ticket.assigned.v1
  • ticket.status.changed.v1
  • ticket.merged.v1
  • customer.updated.v1
  • automation.run.completed.v1
  • service-target.changed.v1
  • satisfaction.received.v1
  • app.navigation.after.v1
  • home.dashboard.after.v1
  • ticket.queue.row.actions.v1
  • ticket.header.actions.after.v1
  • ticket.timeline.after.v1
  • ticket.composer.toolbar.after.v1
  • ticket.requester-context.after.v1
  • customer.profile.after.v1
  • help.article.after.v1
  • settings.after.v1
  • mail.receiver.v1
  • mail.sender.v1
  • record.link.v1
  • voice.provider.v1
  • external.sync.v1
  • commerce.platform.v1
  • ai.provider.v1

Declared limits

Status
estimated
Basis
Capacity and rate values are not load tested and must be replaced by measured limits before the first release. Public request values are per-IP one-minute enforcement thresholds, not capacity proof. Attachment content types are a product decision, not a measurement.
Concurrent Operators
25
Tickets
50,000
Messages
250,000
Inbound Messages Per Minute
20
Outbound Messages Per Minute
20
Active Automation Rules
20
Attachment Bytes Per File
10,485,760
Attachment Bytes Total
10,737,418,240
Attachment Content Types
image/png, image/jpeg, image/gif, image/webp, application/pdf, text/plain, text/csv, message/rfc822, application/zip, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Public Requests Per Minute Per Ip
  • Assets 240
  • Health 60
  • Landing 60
  • Sign In 10
  • Survey 30
  • Provider Webhooks 120
  • Integrations 120
  • Help Centre 60
  • Help Request 20
  • Widget 30

Requirements

All 109 clauses of Lily’s CONTRACT.md. They say what the project must do; the handover and verification records say what is built and tested.

HOME 1 clause

  1. HOME-001
    Deployment front door. GET / presents the configured business name, a short configured description of its support service, links to the public Help Centre and configured public request surfaces, and a sign-in link to /signin. It contains no vendor pricing, trial, billing, product-switcher, or marketing claims.

APP 1 clause

  1. APP-001
    Authenticated workspace. An authorised user entering /app can reach Home, Views, Tickets, Customers, Help Centre, Analytics, Channels, and Administration according to their role. Navigation has a compact responsive form, global search, keyboard shortcuts for search/navigation/common ticket actions, contextual coach marks, and a dismissible setup checklist whose completed state is per Administrator. An unavailable optional channel or adapter is labelled unavailable with the configuration action rather than simulated data.

ACCESS 4 clauses

  1. ACCESS-001
    Roles. Lily has Administrator, Agent, Contributor, and Light Agent roles. Administrators manage deployment-wide settings, people, groups, forms, roles, channels, and policies. Agents work tickets and public replies. Contributors can make internal contributions only. Light Agents have the explicitly configured limited ticket access. An authenticated person may perform only actions permitted by their role and any ticket/group restriction.
  2. ACCESS-002
    Groups and membership. Administrators create, rename, retire, and populate groups. A ticket can be assigned to a group and then an agent; group assignment is visible in views, history, filters, reports, and exports. Retiring a group requires an explicit reassignment or unassignment of its open tickets and retains historical attribution.
  3. ACCESS-003
    Authorisation and lifecycle. Administrators invite, suspend, restore, and remove agents. Removing an agent unassigns their active tickets and preserves the author identity on earlier messages, notes, and audit records. The last active Administrator cannot be removed. Agents configure their own signature and notification preferences; the configured signature is appended only to their public email reply.
  4. ACCESS-004
    Concurrent edits. Each case mutation supplies the revision it was based on. A stale mutation returns 409 and makes no partial field, status, note, assignment, automation, or outbound-message change. An accepted inbound message is durable even if it races with an agent edit.

TKT 18 clauses

  1. TKT-001
    Creation. A human customer email to the support address or an agent's manual submission creates one ticket with an immutable ID, creation time, customer, channel, subject, initial message, declared ticket custom fields, and revision. A new ticket is Open with Normal priority unless the creating agent chooses another priority.
  2. TKT-002
    States and pending reasons. A ticket is Open, Pending, Solved, Closed, or Merged. Pending carries exactly one configured reason, and every reason declares whether it waits on the customer; a ticket is never Pending without a reason. Solved records an agent-confirmed outcome, Closed is immutable archival history, and Merged is an immutable redirect under TKT-016.
  3. TKT-003
    Customer reply. A qualifying human customer message on an Open, Pending, or Solved ticket appends to that ticket, makes it Open, and clears its pending reason. A message matching Closed creates a linked new ticket; a message matching Merged appends to the destination under TKT-016. No qualifying human customer message is discarded.
  4. TKT-004
    Auto-close. A Solved ticket closes seven days after it was last solved unless a qualifying human customer message arrives first. Closing never deletes messages, evidence, executions, or audit history. Policy: ticket.auto-close.v1; default: seven days.
  5. TKT-005
    Queues and views. Agents can filter tickets by status, pending reason, priority, assignee, group, tag, channel, service-target state, and ticket custom fields; sort by target due time, last activity, or priority; and save a named view that authorised agents can open. My queue lists Open and Pending tickets assigned to the current agent, earliest target due time first.
  6. TKT-006
    Search. Full-text search over ticket IDs, subjects, message bodies, customer names and email addresses, tags, and configured custom fields returns matching authorised tickets within 500ms at the stated limits.
  7. TKT-007
    Assignment. New tickets are assigned by the assignment policy. Agents may assign or reassign a ticket to one agent, one group, or both without changing state or service clocks. Policy: ticket.assignment.v1; default: unassigned.
  8. TKT-008
    Priority. Every ticket has Urgent, High, Normal, or Low priority. Authorised agents and allowed automation may change it; each change records actor, prior value, new value, and time.
  9. TKT-009
    Timeline. The ticket timeline presents customer messages, public replies, internal notes, system events, adapter evidence, automation runs, and execution records in durable event-time order, with insertion order as a stable tie-breaker across reload and pagination.
  10. TKT-010
    Public and internal messages. Public replies are eligible for customer delivery. Internal notes are a distinct stored kind that cannot be passed to a delivery adapter, included in customer-facing export, or used to claim an action completed.
  11. TKT-011
    Solved guard. Solving is an explicit agent action and sends no draft or external action. A Solved ticket rejects new public replies and external executions until it is reopened under TKT-003 or TKT-015; Closed and Merged tickets reject them permanently.
  12. TKT-012
    Concurrent changes. Each ticket mutation supplies its revision. A stale mutation is rejected with the current revision and makes no partial change; inbound message append never fails because of a concurrent agent edit.
  13. TKT-013
    Ticket merge. An agent may merge only tickets for the same customer, neither Closed nor Merged, after confirming source and destination IDs and a reason. The source becomes Merged and stores the destination ID. Cross-customer merge is refused; it needs a separately versioned, elevated extension with explicit participant and recipient reconciliation before customer-visible data could cross a customer boundary.
  14. TKT-014
    Manual tickets. An agent-created ticket records whether its initial message came from the requester or agent, and that attribution is immutable. Agent-originated tickets start no first-response clock and are excluded from first-response reporting.
  15. TKT-015
    Operator reopen. An agent may reopen Solved to Open with a required reason; it starts a new service cycle, sends nothing, and records the action. Closed and Merged tickets cannot be reopened.
  16. TKT-016
    Merged history and replies. A Merged ticket is read-only, its timeline is presented on the destination, replies addressed to stored threading identifiers reach the destination, and both IDs remain resolvable in search and audit history. Its source conversation stays linked to the immutable source and is transcluded on the destination with original conversation and author identity. Source and destination retain independent lifecycle and completion histories; routing or transclusion changes neither lifecycle.
  17. TKT-017
    Tags. Agents apply and remove case-insensitive canonical tags on tickets and customers; each change records actor and time. Tags filter queues, match search, serve as automation conditions and report breakdowns, and appear in export. Removing a tag retains the audit event.
  18. TKT-018
    Reply outcome. Sending a public reply leaves the ticket Pending with a configured reason that waits on the customer, unless the agent selects a different permitted status before sending. Sending never solves a ticket alone. Policy: ticket.reply-status.v1; default: Pending, waiting on the customer.

CASE 10 clauses

  1. CASE-001
    Numbered case and default conversation. A Lily case is the visible numbered ticket. Its public number is unique for the deployment life, never reused after deletion or merge, and remains resolvable after import. Each new ticket creates one hidden conversation by default. Customer-visible messages live on that conversation; notes, evidence, assignment, actions, and lifecycle live on the case. Completion never closes or deletes the conversation.
  2. CASE-002
    View predicates and columns. A saved view has an All block and an optional Any block. It matches when every All condition matches and, when Any is non-empty, at least one Any condition matches; an empty All block is true and an empty Any block imposes no additional condition. Rows, counts, exports, dashboard drill-through, sorting, pagination, and selected columns use the same stored predicate.
  3. CASE-003
    Forms, followers, context, and work tabs. Administrators define ticket forms, required fields, and custom fields; creation preserves the selected form and submitted values. An authorised agent can add/remove followers, who receive ticket.followers.v1 updates without needing to be owner or assignee. Detail exposes requester context, selected columns, filtered activity types, and configured tabs. Policy: ticket.followers.v1; default: assignment, requester message, note, public reply, at-risk, breach, and solved events notify followers subject to preferences.
  4. CASE-004
    Bulk and destructive work. An authorised agent can apply reviewed bulk assignment, tag, status, macro, or spam actions to a filtered selection with independent per-ticket success, skip, or failure outcomes. Spam marking, requester suspension, deletion, and restoration require the separately authorised destructive action and preserve audit history under baseline retention.
  5. CASE-005
    Agent and mobile work. Home presents assigned/followed work, capacity, activity, and queue links; availability influences only later routing. The responsive mobile workspace supports ticket work and each agent can configure mobile notification categories and quiet hours with the same routing and suppression semantics as NOTIFY-001 and NOTIFY-002.
  6. CASE-006
    Live conversation. A configured widget may keep a live visitor/agent conversation. Each live conversation has a visible participant and queue state, is linked to its ticket when a request is submitted or an agent creates one, and retains its message chronology when it becomes the ticket's hidden conversation. An agent presence indicator never claims a live responder when none is assigned.
  7. CASE-007
    Global and recent search. Global search returns authorised tickets, customers, organisations, Help Centre articles, agents, groups, and saved views, identifies the matched type and field, and keeps a per-agent recent-record list that can be cleared. Ticket full-text latency remains TKT-006; global results preserve access checks and do not reveal a recent record after access changes.
  8. CASE-008
    Work affordances. Agents can open concurrent ticket tabs without losing unsaved drafts, return to a chosen tab, and see its current revision or conflict state. A queue can offer an explicit guided next-ticket action based on its visible ordering; its action, selection rationale, and any skipped ticket are recorded. The exact guided-play interaction is a Lily decision because the available Zendesk capture establishes the surface but not its execution.
  9. CASE-009
    Tag entry. Ticket tags display as removable chips, offer existing canonical tags while typing, and permit an authorised agent to create a new tag inline. Each entry/removal is audited. Autocomplete and inline creation are Lily product requirements; the cited Zendesk evidence establishes display and removal only.
  10. CASE-010
    Rich composition, counters, and capacity. The composer persists rich formatting, emoji, links, and accepted attachments before submit. Workspace chrome shows authorised agents live conversation and assigned-work counters. Administrators set an enforced per-agent active-ticket cap; routing skips capped agents and records the reason, while direct assignment above the cap requires an explicit authorised override.

MAIL 14 clauses

  1. MAIL-001
    Inbound email. A signature-verified provider delivery to a configured support address creates or appends a ticket message within 60 seconds, preserving sender, recipients, subject, sanitised text and HTML, attachments, provider ID, and threading headers.
  2. MAIL-002
    Threading. An inbound email appends only when In-Reply-To or References matches a stored message ID, or a valid Lily-issued opaque reply token identifies its ticket, and its sender is the current requester or current participant. The timeline audits which identifier matched. A removed or unknown sender starts a new ticket even with a valid identifier; sender and subject alone never join mail.
  3. MAIL-003
    Threading conflict. An unmatched message starts a new ticket. Conflicting headers, or a valid token that disagrees with them, start a new ticket with a visible conflict event naming both candidate tickets; the message is never attached speculatively.
  4. MAIL-004
    Inbound idempotency. Replaying one provider event with the same provider message ID produces one stored message, one service-cycle effect, and at most one routing, acknowledgement, and automation effect. Provider-event ID and RFC Message-ID are durably one-to-one. If either known identity arrives paired with a new, conflicting identity or immutable thread metadata, Lily quarantines the conflict without routing, service-cycle, acknowledgement, or automation effect until reviewed. Body equality never resolves it.
  5. MAIL-005
    Automatic mail. Mail with automatic, bulk, delivery-status, receipt, or no-reply signals is non-actionable. A matching item is stored as a visible system event and does not reopen, notify, start a service cycle, run automation, or request an acknowledgement. An unmatched item creates no queue entry and is retained as a discarded-mail audit record.
  6. MAIL-006
    Outbound email. A public reply atomically creates one durable outgoing message and one dispatch job with a stable idempotency key, reply headers, and a Lily-issued opaque reply token, then dispatches that job within 60 seconds. It uses the ticket's stored reply mailbox: the first configured support-address match retained from RFC intake under MAIL-011, or, for a manual, web-form, widget, or other non-RFC ticket, exactly one enabled configured support mailbox selected and stored by an authorised agent before its first public reply. A repeated key returns the original message and dispatch job.
  7. MAIL-007
    Delivery state. Each outgoing message monotonically progresses through queued, accepted, delayed, delivered, bounced, rejected, suppressed, failed, or needs_review. Provider acceptance is never customer delivery. There are at most five total dispatch attempts in one hour with the original key. A failure before provider acceptance never stops a first-response clock. Lily preserves provider-acceptance time and delivery evidence. If the sole qualifying public reply later reaches final bounced, rejected, or failed state, it restores that service cycle's original first-response clock and target due calculation without resetting elapsed time; if another qualifying public reply remains provider-accepted, the clock stays stopped. The pre-send ticket status and its mutation revision are recorded; on that same sole-reply final failure, Lily restores the pre-send status only when no later independent status mutation occurred, never clobbering later agent changes. Final failure or needs_review notifies under NOTIFY-004. An ambiguous needs_review outcome is never automatically retried and requires provider reconciliation.
  8. MAIL-008
    Authoritative delivery reports. Verified provider reports move an accepted message only forward to delivered, delayed, bounced, or rejected and record report time. Duplicate or out-of-order reports never regress a terminal state; Lily never labels delivery without an authoritative report.
  9. MAIL-009
    Attachments. Inbound and outbound attachments remain bound to their immutable message. A file outside the seed limits is rejected with filename and reason while the readable message and accepted files are retained.
  10. MAIL-010
    Provider events. Intake and delivery webhooks are rejected without a valid mail.receiver.v1 signature. Duplicate and out-of-order delivery events are tolerated and never create data or regress a terminal state.
  11. MAIL-011
    Recipients and support-address intake. One RFC message addressed to multiple configured support addresses creates one intake record, retains every matched support address, and records the first configured match as its reply mailbox. A new ticket records the sender as requester and only non-support To and Cc recipients as participants; Bcc is never disclosed. A public reply addresses the requester and current participants the agent keeps in the composer; removed recipients are not restored later. Support and notification addresses are never participants.
  12. MAIL-012
    Intake durability and destination. Lily acknowledges a verified intake only after a durable intake record exists; failure before it returns 503 with no partial ticket. Post-record parse, storage, or enqueue failure is visible with a retryable or terminal reason. A verified message with no configured support destination is quarantined with destination and reason.
  13. MAIL-013
    Mailbox identity. An agent-authored public reply uses the ticket's stored reply mailbox: the first configured RFC support-address match under MAIL-011, or the authorised enabled configured-mailbox selection stored under MAIL-006 for a manual, web-form, widget, or other non-RFC ticket. It carries ticket threading data and appends that agent's configured signature. Operator notifications use a no-reply address that is not a support destination and carry no agent signature. Automatic acknowledgement is not a notification and follows MAIL-014.
  14. MAIL-014
    Automatic acknowledgement. When enabled, the actionable message that creates a ticket produces exactly one stored automatic acknowledgement under MAIL-006 through MAIL-008. It uses the ticket's stored reply mailbox and threading data but no agent signature; it is not sent from the no-reply notification address. No acknowledgement is sent for manual, non-actionable, blocked, or later ticket messages, and it never counts as a first response. Policy: channel.autoresponder.v1; default: disabled until an Administrator enables it for a mailbox.

CHAN 6 clauses

  1. CHAN-001
    Channel catalogue. Administrators see every configured intake and delivery channel, its enabled state, form or mailbox binding, group routing, public address, and configuration health. Disabling a channel preserves its history and stops only later intake or dispatch through that channel.
  2. CHAN-002
    Web widget and simulator. A configured public widget collects a request with the configured form and creates a ticket under TKT-001. It identifies the current requester where consented, exposes the required privacy text, and confirms a successful request without pretending an agent is present. An Administrator can use a simulator to preview configured form, bot, appearance, proactive-message, and live-conversation states without creating a real ticket or sending a visitor message.
  3. CHAN-003
    Grounded bot assistance. A configured bot greets the visitor, offers up to ten article-grounded generated answers from approved Help Centre material, and shows cited article links. It stores every bot and visitor turn before agent handoff in the linked conversation, collects the ticket form, and hands off for no valid answer or visitor request. Core ai.provider.v1 receives only approved article material and disclosed visitor input, never private notes; cited identifiers are validated against supplied articles and invalid output fails for review rather than falling back to invented copy.
  4. CHAN-004
    Proactive messages. An administrator can configure an eligible widget audience and a reviewed proactive message. The configuration states its trigger and frequency limit, respects consent and suppression, and records each presentation; it does not create a ticket unless the visitor submits a request.
  5. CHAN-005
    Voice queue and ticket link. A configured voice adapter exposes queues or lines with waiting-call count, agent or group routing context, call state, and stable Ticket ID when one exists. An authorised agent can attach a call record to an existing ticket; the attachment is audited and adds no invented call-to-ticket relation when no ticket was selected. This is a Lily lifecycle decision; the Zendesk evidence only establishes a Live Calls Ticket ID column.
  6. CHAN-006
    Side conversations. An authorised agent can open a labelled side conversation with an approved external participant, see its delivery state and replies on the ticket, and keep it separate from the customer-visible conversation. It cannot disclose private notes without an explicit reviewed message.

CUST 7 clauses

  1. CUST-001
    Identity. The first qualifying customer message from an unseen normalised email address creates one customer; comparison is case-insensitive and a shared display name never merges identities.
  2. CUST-002
    Profile. A profile has display name, primary and observed email addresses, locale, tags, declared custom fields, and private account notes. Locally owned fields are editable and adapter-sourced fields are read-only with source and refresh time.
  3. CUST-003
    History. A profile shows every Open, Pending, Solved, Closed, and Merged ticket for that customer with its satisfaction and available adapter records.
  4. CUST-004
    Notes. Agents may add private, attributed customer notes. Notes are never sent to the customer or written back through an adapter.
  5. CUST-005
    Merge. An agent merges customers only after confirming survivor and source IDs and seeing addresses, ticket counts, and record links. Tickets, addresses, notes, tags, fields, and audit history move to the survivor; incompatible provider customer IDs block the operation and name the conflict.
  6. CUST-006
    Erasure boundary. Erasing a customer removes locally owned messages, attachments, notes, evidence snapshots, and tickets under BASE-DATA-003; it never claims to erase a provider account or provider data.
  7. CUST-007
    Resync suppression. This predecessor guarantee applies only to an enabled external.sync.v1 extension described in research/optional-commerce-adapter.md: erasure stores a one-way keyed digest of normalised provider namespace and resource ID, no customer field, to prevent automatic resync recreation; it travels with export/import and only explicit restore removes it. Core Lily has no automatic external sync or sync credential.

CUSTOMER 2 clauses

  1. CUSTOMER-001
    Organisations and suspension. Administrators create organisations and membership. An authorised agent may suspend a requester; Policy: requester.suspension.v1; default: new intake is quarantined for review while earlier history stays readable.
  2. CUSTOMER-002
    Imports and record links. An Administrator can run a reviewed CSV customer import with mapping, validation, duplicate handling, and per-row outcomes. An optional record-link adapter attaches named external records with adapter, identifier, link state, and retrieval time; unavailable data is labelled unavailable and never fabricated.

HELP 5 clauses

  1. HELP-001
    Public Help Centre and audiences. An Administrator activates or deactivates the public Help Centre; deactivation makes public article and request paths unavailable while preserving authoring history. Published content is visible only to its named audience. An audience selects signed-in users, staff, groups, tags, and users with All/Any blocks: all All conditions and, when non-empty, one Any condition must match; empty All is true and empty Any adds no restriction. Administrators preview matching users and anonymous/staff roles. A preview is not evidence of signed-out deployment reachability.
  2. HELP-002
    Articles, taxonomy, history, and bulk work. Agents with article authority can create, edit, publish, unpublish, archive, and restore articles in categories and sections. Articles have a title, body, author, timestamps, lifecycle state, audience visibility, content tags, and version history. Article history is filterable by actor, event, and date. A selected article set supports reviewed bulk publish, unpublish, archive, restore, category, and audience changes with per-item success, skip, or failure results.
  3. HELP-003
    Findability and media. The Help Centre offers text search, category navigation, pagination, article metadata, a shared media library with upload, search, insert, and removal permissions, and article comments when comments are enabled. Search results respect audience visibility and label unavailable translations or attachments rather than substituting a different article.
  4. HELP-004
    Languages and appearance. Administrators configure Help Centre languages, translated article variants, branding, theme appearance, and a reviewed public preview. A language fallback is explicit and never represents untranslated copy as a translation.
  5. HELP-005
    Help Centre requests. A public request form uses an administrator-selected ticket form, validates required fields, creates a ticket under TKT-001, and gives the requester a result that does not expose another ticket. Its submission is distinguishable from article comments and widget intake.

ADMIN 2 clauses

  1. ADMIN-001
    Operational settings. Administrators configure business hours, IANA timezone, holiday calendar, ticket types and priorities, statuses, forms, custom fields, canned replies, mailbox identities, routing, authentication, retention, and API/webhook credentials. Retention configuration can label, report, or schedule review of records but cannot automatically delete user data; deletion follows the applicable baseline clause and explicit authorised action. The settings screen distinguishes active configuration from unavailable optional adapters.
  2. ADMIN-002
    Business rules, capacity, and usage. Administrators can inspect routing rules, capacity limits, API/webhook integrations, installed approved applications, their last execution or error, and current storage/API/channel usage meters with source, period, and refresh time. No setting silently expands authorisation or gives an external application access beyond its configured scope.

MACRO 3 clauses

  1. MACRO-001
    Macro library. Authorised agents create, edit, archive, and search shared macros for a public reply or internal note. A macro may propose tags, priority, assignment, form fields, or status, but does not itself send a message. The library reports applied count, recent use, and sortable rolling seven-day usage without exposing ticket content to an unauthorised viewer.
  2. MACRO-002
    Placeholders. Applying a macro resolves its declared placeholders from the current ticket, requester, organisation, and agent. An unresolved required placeholder blocks use and identifies the missing value.
  3. MACRO-003
    Review boundary. A macro fills an editable draft and previews every field change. Submitting remains an explicit TKT-018 and MAIL-006 action and cannot bypass revision, authorisation, or outbound delivery rules.

SLA 6 clauses

  1. SLA-001
    Calendar and selection. Administrators configure first-response and resolution targets against one workspace timezone, working-hours schedule, and holiday calendar. Policy: service-target.selection.v1; default: targets are selected by ticket priority and measured in business time. A ticket with no matching target displays that fact and is excluded from met/breached denominators.
  2. SLA-002
    Snapshot and calculation. Starting a service cycle stores the target version, duration, due time, and business-calendar inputs. Later setting edits do not rewrite its result. Recalculation records its reason and prior due time.
  3. SLA-003
    First response. The first-response clock stops only when the first public agent reply is provider-accepted, subject to MAIL-007's sole-qualifying-reply final-failure restoration. Assignment, notes, macros, automation, an acknowledgement, and queued or failed delivery do not stop it.
  4. SLA-004
    Resolution cycle. The resolution clock runs for Open, and for Pending unless the selected pending reason explicitly waits on the requester. It stops when the case is solved. A requester message or agent reopen starts the next cycle while retaining prior cycles.
  5. SLA-005
    Visibility. Ticket rows, ticket detail, Home, and saved views show the exact due time, calendar basis, remaining or overdue time, and state active, paused, at_risk, or breached. At risk begins at 25% of target duration remaining in business time.
  6. SLA-006
    Breach effects. Crossing a target marks the cycle breached, emits a notification event, and never resolves, closes, reassigns, or otherwise mutates the ticket on its own.

QUEUE 5 clauses

  1. QUEUE-001
    Filter-exact dashboard. Home shows the current selected view's open backlog, urgent count, target-state counts, resolved-today count, mean first-response time over the last 24 hours, and satisfaction score over the last 7 days. For every ticket state it shows the count and longest current wait. Every count opens the equivalent saved-view conditions and shows the data timestamp; it is no more than 30 seconds old at the stated limits.
  2. QUEUE-002
    Target tiers. An active ticket with a target is exactly one of breached once past due, at_risk with 25% or less of its target duration remaining, due_soon with more than 25% remaining and two business hours or less to due, or later otherwise. A paused cycle is paused; a ticket with no matching target is no_target. The four active-target tiers are mutually exclusive and exhaustive.
  3. QUEUE-003
    Operational ordering. The default work ordering is breached, at_risk, due_soon, later, paused, no_target, then nearest active due time, priority, latest requester activity, and ticket number. An agent may choose documented alternatives without changing the selected view conditions.
  4. QUEUE-004
    Due-state detail. A queue and ticket disclose which target is due, absolute due time with timezone, and the previous/current due time and reason for a recalculation.
  5. QUEUE-005
    Measured times. First-response and resolution measures are stored as business and calendar elapsed time and shown with their cycle. Reopening never overwrites a recorded first response.

AUTO 7 clauses

  1. AUTO-001
    Rule lifecycle. A rule is Draft, Active, or Paused and has a name, ordered conditions and actions, creator, latest editor, version, and run count. Draft and Paused rules process no new events.
  2. AUTO-002
    Allowed actions. A rule can react to ticket creation, requester message, ticket field or status change, or one scheduled elapsed-time condition. It may apply a tag, set priority, assign an eligible group or agent, set a pending reason, send an internal notification, or apply a macro draft. It cannot send a public reply, complete a ticket, change a requester record, or invoke an external mutation. Policy: automation.action-allowlist.v1; default: the listed actions only.
  3. AUTO-003
    Order and audit. Active rules evaluate in visible order against one immutable triggering revision. Each run records matching conditions and each applied, skipped, or failed action.
  4. AUTO-004
    Idempotency and loops. A rule run is unique by rule version, ticket, triggering event or scheduled window, and action. An evaluation chain evaluates each active rule version at most once; duplicate events and scheduler runs repeat no effects.
  5. AUTO-005
    Concurrent changes and failure. A rule rechecks its conditions and ticket revision before mutation. A conflict is a visible skipped run. A failed action is visible with rule, ticket, attempted action, and error; a retry reuses its idempotency key.
  6. AUTO-006
    Rule authorisation. Only an Administrator may activate, pause, or change a rule's owner-visible scope. A rule cannot act on a ticket, group, form, or field its owner is not authorised to configure.
  7. AUTO-007
    Reviewed recovery. A retried failed rule run uses the original triggering revision and idempotency keys, reports any now-stale condition, and never replays an action that already succeeded.

NOTIFY 4 clauses

  1. NOTIFY-001
    Accountable ticket updates. New unassigned tickets notify every eligible Agent; direct assignment notifies the new assignee or every eligible member of the assigned group; self-assignment sends nothing. Requester follow-up, at-risk, breach, and solved notifications go to followers, or to the assignee then eligible Administrators if there are no followers. An at-risk and a breach notification occur at most once each per service cycle.
  2. NOTIFY-002
    Coalescing and quiet hours. Repeated requester-follow-up events coalesce to one notification until an assigned agent opens the ticket; repeated event categories use their named service-cycle or open-cycle boundary. Policy: ticket.quiet-hours.v1; default: quiet hours defer non-urgent notifications while urgent and breached work bypasses them. Intake, service clocks, and other recipients are unaffected.
  3. NOTIFY-003
    No mail loops. Notifications use a configured no-reply sender that is not a support destination. Mail to that address creates or reopens no ticket and triggers no automation. Automatic acknowledgements are ticket mail under MAIL-014, not notifications.
  4. NOTIFY-004
    Failure reaches a person. A public-message delivery failure, automation failure, notification failure, or configuration/security failure is visible on the ticket or settings record and is delivered to the initiating agent, or every active Administrator when there is no initiating agent. This responsible-failure notification cannot be muted and never blocks or rolls back its causing event.

CSAT 3 clauses

  1. CSAT-001
    Survey request. A solved ticket with a customer-visible accepted reply can queue one signed satisfaction request for that solve cycle. Policy: csat.request.v1; default: one email 24 hours after the solve. No survey is sent to a blocked requester, and reopening cancels an unsent request.
  2. CSAT-002
    Survey response. The single-use public link accepts one whole-number rating from one to five with an optional comment, expires after 30 days, exposes no unrelated ticket data, and never creates or reopens a ticket.
  3. CSAT-003
    Survey history. A result shows on the ticket and customer record with its solve cycle and time. A later cycle makes a new request and never overwrites a prior result.

INSIGHT 8 clauses

  1. INSIGHT-001
    Operational dashboards. Analytics provides prebuilt dashboards for ticket volume and status, first-response and resolution duration, service-target outcomes, satisfaction score and response rate, assignment and group workload, and channel mix.
  2. INSIGHT-002
    Dataset and filters. Every report states its period, timezone, selected view or filters, ticket states, denominator, freshness time, and comparison period. It can filter by assignee, group, type, priority, tag, form, channel, custom field, and target state.
  3. INSIGHT-003
    Report builder. An authorised user can create, edit, save, share, and retire a report using documented ticket, customer, satisfaction, and service-target fields. A report exposes the tickets behind an aggregate only to viewers authorised for those tickets.
  4. INSIGHT-004
    Formatting and export. Dashboard and report users can choose supported chart and table formatting. An export contains the complete durable result for current filters and period with metric definitions, rather than only the rendered page.
  5. INSIGHT-005
    Freshness and correctness. Ticket, service-target, and satisfaction analytics reflect committed mutations within five minutes at the stated limits. A panel shows its last successful refresh and a stale or failed state; no cached result is represented as current.
  6. INSIGHT-006
    Operational export. An agent can export the complete durable current result of an authorised view, queue, dashboard, or report, including selected filters, period, and metric definitions. This convenience export does not replace DATA-001.
  7. INSIGHT-007
    Merge accounting. A merged source remains auditable and searchable but is excluded from live backlog, created, solved, and service-target totals. Its source conversation entries remain visible through canonical transclusion without double-counting the canonical case.
  8. INSIGHT-008
    Explainable drivers. Each classified volume, satisfaction, or service-target aggregate exposes its contributing tag or configured classification, stated denominator, and authorised ticket drill-down. Unclassified eligible tickets appear as Other; the displayed drivers, Other, and excluded denominator reconcile to the reported total.

DATA 3 clauses

  1. DATA-001
    Portable export. Lily's complete export includes tickets, cases, conversations, messages, attachments, customers, organisations, forms, tags, views, macros, service cycles, automations and runs, satisfaction records, settings, article versions, record links, notifications, and audit entries, with original attachments. It contains no secret and follows baseline data guarantees.
  2. DATA-002
    Data boundaries. Export, retention, deletion, and erasure identify locally owned data and optional-adapter references. Lily does not claim to update, delete, export, or erase a provider record unless the configured adapter returned a confirmed result for that operation.
  3. DATA-003
    Zendesk importer. An Administrator can use the documented importer with an administrator-provided Zendesk export into an empty Lily installation. It validates mappings before mutation and offers dry run. It imports numbered tickets, requesters, messages, original attachments, tags, forms, groups, users, status history, merge history, and available metadata, with a per-record outcome and one import audit record. Each source object has a preserved source ID and a Lily ID; source ticket numbers are retained only when unused, otherwise Lily allocates the next permanent number and records the source-number mapping. Existing source IDs make reruns idempotent. Imported merge and status history are retained as source history; unsupported data receives a per-record outcome without fabrication. Stage 2 must prove this with a real export; no Freshdesk importer is committed.

Baseline

Selected ownership clauses from the 22 in the project’s BASELINE.md. They are declared requirements; evidence is recorded separately.

  1. BASE-DATA-005
    Independence. The deployment makes no request to the marketplace or the seed author. There is no telemetry, phone-home, licence check, or kill switch.
  2. BASE-DATA-001
    Export and import. pnpm run export produces every record and attachment; pnpm run import restores it into an empty deployment; export, import, export yields an archive with equivalent contents.
  3. BASE-DATA-004
    Outbound flows. User data leaves the deployment only through externals declared in seed.json → externals. No other outbound request carries user data.
  4. BASE-PUBLIC-001
    Privacy. Public surfaces (widgets, booking pages, forms, status pages) set no cookies, load nothing from third-party domains, and send no visitor data before the visitor's first interaction.
  5. BASE-SECRET-001
    No leakage. No secret appears in the client bundle, in logs, or in an error response.

View as agent

Everything on this page is in these files, copied unmodified from the release. An agent evaluating Lily can read them instead of the page.

ACCEPTANCE.md
What the publisher accepts as a finished release.
AGENTS.md
Instructions for the coding agent that maintains an installation.
AUTHORING.md
How the project’s source is authored from shared components.
BASELINE.md
The baseline requirements the project declares.
CONTRACT.md
The requirements on this page, in source form.
HANDOVER.md
Maintainer orientation and verification status.
OPERATIONS.json
The machine-readable operating description.
OPERATIONS.md
How the project is set up, operated and deployed.
README.md
Source setup, available commands and implementation status.
edition.json
The source recipe: which shared components the project selects.
seed.json
The manifest: capabilities, outside services, extension points, limits, operating cost and deployment needs.
sources.lock.json
The locked bytes of those components.

Every project, with its availability, is in /agents/catalogue.json; the agents page describes the machine-readable files.