Seed catalogue · Sales

Orbit

A CRM for one revenue team that turns customer activity reported by the tools they already run into explainable, human-reviewed next actions.

Licence
MIT
Family
Sales
Edition
Orbit
Version
0.1.0
Contract
64 clauses across 10 areas
Maturity
complete-workflow-implementation; acceptance requires pinned runtime and native receipts
Orbit screenshot 1: verification ui 1440 app notifications
Orbit screenshot 2: verification ui 1440 app records
Orbit screenshot 3: verification ui 1440 app settings
Orbit screenshot 4: verification ui 1440 app sources
Orbit screenshot 5: verification ui 1440 app
Orbit screenshot 6: verification ui 1440 assistance preview

6 screenshots from the product's own visual and verification artifacts. Its handover records what was exercised.


What you get

Everything below is generated from the seed's own manifest and contract. No rounded-off claims, no numbers we made up.

Operating cost

Runs on your cloud's free tier

The seed declares the free plan as the default deployment. Its own estimate, thresholds and sources are below, unedited.

Currency
USD
Period
month
Estimated
yes
Low
0
High
10
Assumptions
Cloudflare platform only, excluding buyer-selected mail and AI adapters: Workers Free is the $0 default while daily Worker requests stay at or below 100000, D1 stays at or below 5000000 rows read and 100000 rows written per day, R2 stays within its monthly free tier, and Queues stays at or below 10000 operations per day. Workers Paid is required to sustain the declared 600 signed-ingress requests per minute (864000 requests/day): 600 * 60 * 24 * 30 = 25920000 monthly Worker requests, or 15920000 above the 10000000 Standard-plan inclusion. At $0.30 per additional million, that is $4.78 request overage plus the $5 monthly Paid minimum, rounded up to the $10 high; this excludes CPU, D1 overages, and future Queue fan-out, which must be measured before those capabilities ship. One public IP at the declared 300 requests per minute reaches the Free Worker request ceiling in about 5.6 hours. Sources: https://developers.cloudflare.com/workers/platform/pricing/ ; https://developers.cloudflare.com/d1/platform/pricing/ ; https://developers.cloudflare.com/queues/platform/pricing/
Status
estimated; not load verified

Externals declared

2 externals, each with a reason

Under BASE-DATA-004, user data leaves only through what is declared here.

sendgrid
Native sign-in and operator-approved mail require an external delivery provider.
openai
Generate operator-requested recommendation explanations and drafts from the exact reviewed preview.

Extension points

30 declared integration conveniences

These hooks are optional conveniences. Owners may change any source, including core logic, schema and infrastructure; their agents adapt useful upstream fixes and verify the result.

signal.sources.v1operator.management.v1record.identity.v1opportunity.assignment.v1opportunity.scoring.v1opportunity.prioritization.v1opportunity.next-action.v1outreach.instructions.v1outreach.quiet-hours.v1signal.recorded.v1record.merged.v1opportunity.evaluated.v1opportunity.queue-changed.v1recommendation.created.v1outreach.scheduled.v1outreach.accepted.v1outreach.failed.v1notification.created.v1navigation.after.v1now.header.after.v1now.row.actions.v1contact.sidebar.after.v1company.sidebar.after.v1opportunity.header.after.v1opportunity.sidebar.after.v1opportunity.timeline.after.v1composer.context.after.v1settings.sections.after.v1mail.sender.v1ai.provider.v1

Declared limits

Capacity, stated up front

Straight from seed.json → limits. Where a value is an estimate the seed says so.

Status
estimated-until-load-tested
Operators
25
Contacts
100,000
Companies
25,000
Open Opportunities
25,000
Signals
1,000,000
Timeline Activities
2,000,000
Signal Payload Bytes
262,144
Signed Ingress Requests Per Minute
600
Public Requests Per Minute Per Ip
300
Outbound Messages Per Minute
3
Outbound Messages Per Operator Per Rolling Day
100

Non-goals, stated proudly

A product that says what it will never do is a product you can trust to stay small, fast and legible. These are refusals, not gaps.

  • A second workspace
  • Roles, territories, or private records
  • A second pipeline
  • Workflow builder
  • Bulk campaigns or sequences
  • Autonomous customer outreach
  • SMS, phone, or social sending
  • Attachments on outbound messages
  • Email or digest notifications
  • A tracking script, cross-site tracking, fingerprinting, or data-broker identity resolution
  • Hosted forms or landing-page building
  • Marketing CMS, ads, or multi-touch attribution
  • Per-record currencies
  • Plan or pricing pages
  • Revenue forecasting
  • Subscription billing or plan enforcement
  • Native mobile applications

The contract

All 64 clauses of Orbit, from its own CONTRACT.md. Stable IDs identify requirements; the source handover and verification evidence distinguish implemented, tested and uncovered behavior.

TEAM4 clauses

TEAM-001
Equal operators.

Every operator can view and act on every contact, company, opportunity, signal, activity, and notification. There are no roles and no private records.

TEAM-002
Management.

Operators are invited and removed in settings. The operator configured at setup can be removed only by themselves. Policy: operator.management.v1; default: any operator may invite or remove.

TEAM-003
One workspace.

A deployment holds exactly one workspace and offers no way to create a second. Its name, timezone, currency, working hours, stale interval, awaiting-response interval, pipeline stages, signal sources, and free-mail domain list are configured in settings and apply to every record.

TEAM-004
Removal handover.

Removing an operator revokes their sessions, cancels their scheduled messages, and unassigns their open opportunities. Their notes, drafts, sent messages, and timeline entries remain and stay attributed to them.

RECORD13 clauses

RECORD-001
Core records.

Operators can create, edit, and delete contacts, companies, and opportunities. A contact requires a name or an email address and may also hold a phone number, job title, and timezone; a company requires a name and may hold one primary domain; an opportunity requires a title and holds a pipeline stage, a value in the workspace currency, zero or one owner, an expected close date, at most one company, and any number of contacts. Each entity listed in seed.json → customFieldEntities also holds custom fields.

RECORD-002
Associations.

A contact belongs to at most one company and to any number of opportunities. An opportunity with at least one contact names one of them primary, and that contact is the default recipient for its outreach; an opportunity with no contact is never recommended an email follow-up. Changing an association moves no timeline entry: each record keeps the entries it already had.

RECORD-003
Identity keys.

A contact's key is its email address lowercased with surrounding whitespace removed; a company's key is its primary domain lowercased with a leading www. removed. A domain on the configured free-mail list is never a company key. Creating or changing a record to a key another record already holds returns 409 with that record's ID and writes nothing. A record with no key is created and edited normally, and signals never link to it automatically. Orbit never merges records by name similarity, fuzzy match, or score. Policy: record.identity.v1; default: the rules in this clause.

RECORD-004
Duplicate merge.

Merging two contacts or two companies requires an operator to choose the surviving record and the value of every conflicting field. The merge moves associations and timeline entries once, retires the other record's key as an alias so later signals carrying it link to the survivor, creates no signal, recommendation, or outreach, and records the retired ID in the audit trail.

RECORD-005
Timeline.

A record's timeline lists its signals, stage and owner changes, notes, logged calls and meetings, recommendations, drafts, outbound attempts, replies, and merges, most recent occurred time first with ties broken by ID. Every entry shows its occurred time, its recorded time, and the operator, source, or feature that created it.

RECORD-006
Search and views.

Operators can search contacts, companies, opportunities, and timeline text, and can filter opportunities by state, stage, owner, band, and queue. A first page of at most 50 matches returns within 500ms.

RECORD-007
Ownership.

An opportunity has zero or one owner. Any operator can assign or reassign it, and the change appears on its timeline. Policy: opportunity.assignment.v1; default: a new opportunity is unassigned.

RECORD-008
Import.

Operators import contacts and companies from a CSV, mapping its columns to fields once per import. A row updates an existing record only when it carries an Orbit ID or matches exactly one key under RECORD-003; a row matching more than one record fails. The import reports created, updated, and failed rows with row numbers and reasons, and writes nothing for a failed row.

RECORD-009
Duplicate candidates.

Orbit lists contacts sharing a name within one company, and companies sharing a name, as duplicate candidates; names are compared lowercased with runs of whitespace collapsed. A candidate is a review item only: nothing is merged, altered, or hidden until an operator completes RECORD-004.

RECORD-010
Manual entries.

An operator can add a note to any record and log a call or meeting with an occurred time, duration, and attending contacts. A manual entry is attributed to its author, editable and deletable by any operator, never sent to a customer, and never contributes to a score.

RECORD-011
Related records.

A company page lists its contacts and its opportunities with each opportunity's stage, owner, and value, plus the total value of its open opportunities. A contact page lists their opportunities. Both reflect an association change on the next load.

RECORD-012
Contactability.

A contact is contactable or do-not-contact. An operator can set do-not-contact at any time, and an unsubscribe event or a permanent bounce also sets it. No operation sends customer email to a do-not-contact contact, the state is shown wherever the contact appears, and only an operator can clear it.

RECORD-013
Deletion.

Deleting a company detaches its contacts and opportunities and deletes neither. Deleting an opportunity deletes its recommendations, drafts, and unsent scheduled messages, and leaves its contacts, its company, and their entries for messages already sent. Deleting a contact follows DATA-002. Each deletion is confirmed before it runs.

SIGNAL9 clauses

SIGNAL-001
Ingestion.

A valid event from a configured source, carrying that source's signature, becomes one normalised signal within 10 seconds. The signal keeps its source, source event ID, type, subject, occurred time, received time, payload hash, and linking basis, and is never edited afterwards.

SIGNAL-002
Signal types.

Orbit accepts form submissions; email sent, opened, replied, bounced, and unsubscribed events; meeting viewed, booked, completed, and cancelled events; page views; chats; content downloads; and firmographic changes. A source can add a type namespaced to itself, which changes no existing type. An event whose type is neither standard nor namespaced is rejected with 400.

SIGNAL-003
Idempotency.

Repeated or concurrent delivery of one (source, source event ID) produces one signal and one set of downstream evaluations. Reusing that identity with a different payload hash is rejected and recorded as an error on that source.

SIGNAL-004
Linking.

A signal links first by an Orbit record ID the source supplies, then by RECORD-003. A uniquely linked signal appears once on that record's timeline. A signal with no unique match is held in the unlinked queue, where it changes no score; an operator linking it later appends it to the chosen record's timeline exactly once and triggers one evaluation.

SIGNAL-005
Event time.

A late or out-of-order event keeps its occurred time, appears in that position on the timeline, and triggers a fresh evaluation. It never overwrites a record field that a later-occurring event wrote.

SIGNAL-006
Evidence confidence.

Every signal carries one confidence: observed, when the customer acted deliberately (form submission, reply, booking, meeting, download, chat), or inferred, when a tool reported activity (email open, page view). An inferred signal alone cannot create an opportunity, produce a high band, or satisfy ACTION-001's evidence requirement.

SIGNAL-007
No tracking.

Orbit serves no tracking script, pixel, or cookie, and performs no fingerprinting or cross-site collection. A page-view, chat, or download signal is accepted only when its source supplies the visitor identity it already holds and the basis for holding it; without that basis the event is held unlinked under SIGNAL-004 and never becomes contact history.

SIGNAL-008
Ingestion failure.

A missing or invalid signature returns 401, a request naming a source this deployment has not configured returns 403, and a payload over seed.json → limits.signalPayloadBytes returns 413; none of them writes anything. A persistence failure returns 503 and writes no partial signal, timeline entry, or evaluation, so the source can safely replay the same event identity. Each source shows its last accepted event, its last error, and its rejected-event count in settings.

SIGNAL-009
Signed sources.

This clause supersedes BASE-ACCESS-004 for the paths /api/v1/signals/ and /api/v1/mail/events/ only: a request there is authorised by a signature from a source or mail provider configured in this deployment instead of an operator session, and may write only signals, delivery states, and their timeline entries. Every other mutation still requires a valid operator session and a server-side ownership check.

OPP9 clauses

OPP-001
Lifecycle.

An opportunity is open, won, or lost. Closing it as won or lost records the operator, the time, and a reason, and removes it from NOW and NEXT. Later signals append to its timeline and never reopen it; only an operator can reopen it, which returns it to open without changing its stage or owner.

OPP-002
Independent state.

Stage, owner, score, band, and queue state are independent fields. A score or band change never changes stage, owner, or won/lost state, and a stage change never changes a score.

OPP-003
Evaluation.

A linked signal whose type carries a non-zero weight in the scoring policy, or a change to an open opportunity's stage, expected close date, value, owner, or associations, evaluates that opportunity within 30 seconds. The result records a 0–100 score, a low, medium, or high band, the evaluation time, the policy version, and each contributing signal's contribution. A closed opportunity is not evaluated. Policy: opportunity.scoring.v1; default: each contributing signal's configured weight decays linearly to zero over the 30 days after its occurred time, the sum is clamped to 0–100, and 0–39 is low, 40–69 is medium, 70–100 is high.

OPP-004
Explainability.

The opportunity view shows every signal the current score used, by ID, with its source, occurred time, confidence, and positive or negative contribution, and shows the reason for the current recommendation beside them.

OPP-005
Evaluation failure.

If an evaluation fails or returns output that does not validate, the previous score, band, and evidence remain readable and are marked stale with the time of the failed attempt. Orbit shows no score, band, or recommendation it did not compute.

OPP-006
NOW ordering.

NOW lists the open opportunities that OPP-007 placed there, ordered by score descending, then by the occurred time of their most recent contributing signal descending, then by ID. Operators can filter it by owner, stage, and band. Policy: opportunity.prioritization.v1; default: the ordering in this clause, and every factor it uses is shown in the opportunity view.

OPP-007
Queue entry.

An open opportunity enters NOW when its band rises, a customer reply or delivery problem arrives, a scheduled message cannot be sent, its expected close date passes, its last timeline entry becomes older than the stale interval, or an operator puts it there. It is in NEXT while it waits for a scheduled send or for a customer response inside the awaiting-response interval, and in neither when no action is pending. The stale interval defaults to 14 days and the awaiting-response interval to 5 working days, counted Monday to Friday in the workspace timezone. Every entry, move, and removal records its reason and actor on the timeline.

OPP-008
Manual completion.

An operator can complete or skip the current recommended action without sending anything, with an optional note; the outcome, note, and operator appear on the timeline. Policy: opportunity.next-action.v1; default: evaluate once, keep the opportunity in NOW if that produces a new recommendation, and otherwise remove it from NOW and NEXT.

OPP-009
Pipeline stages.

The deployment has one pipeline. Its stages are named and ordered in settings; an opportunity can move to any stage in any order, and each move records the previous stage, the actor, and the time. A stage holding opportunities cannot be deleted until they are moved.

ACTION5 clauses

ACTION-001
Current recommendation.

An open opportunity has at most one current recommended action, which is either an email follow-up or a manual action. It names the action, cites at least one observed signal by ID, and records the policy or model version that produced it. Its written explanation is generated under AI-001 and is absent when AI-003 applies.

ACTION-002
Replacement.

A new contributing signal, a changed opportunity, a completed or skipped action, or an operator request replaces the current recommendation. The replaced one stays on the timeline marked superseded and can no longer be drafted from, sent, or completed.

ACTION-003
Draft on request.

An operator can request a one-to-one email draft for the current recommendation. Generation reads the opportunity, the primary or operator-selected contact, that contact's company, the cited signals, the messages already exchanged with that contact, and the configured instructions, and sends nothing. Policy: outreach.instructions.v1; default: at most 150 words, and no fact, price, discount, or commitment that a cited record or signal field does not carry.

ACTION-004
Durable draft.

Recipient, subject, and body are visible and editable, and the draft is stored with its author, source recommendation, created time, and last edit time, and is readable after signing out and back in.

ACTION-005
Stale draft.

A reply, meeting, unsubscribe, do-not-contact, permanent bounce, changed recipient, changed opportunity, or replaced recommendation marks a draft stale. A stale draft is shown as stale, and sending it returns 409 and writes no outbound message until an operator opens it, sees what changed, and confirms.

OUT12 clauses

OUT-001
Human send boundary.

No signal, score, recommendation, draft, job, or AI result can approve or start a customer message. A send requires an authenticated operator who has seen the exact recipient, subject, and body to invoke it, and a worker may dispatch only the unchanged content an operator approved for the schedule in OUT-009. No policy, adapter, extension, or setting removes this requirement.

OUT-002
Message states.

Customer mail is submitted through mail.sender.v1. An outbound message is draft, scheduled, queued, reconciling, accepted, delivered, bounced, failed, cancelled, or delivery-unknown. The operator view calls a message sent only after the provider accepts it, and delivered only after a delivery event.

OUT-003
Send idempotency.

Repeated or concurrent use of one send idempotency key creates one outbound message and at most one provider submission.

OUT-004
Threading.

An outbound message carries message and reference headers that return the customer's reply to the same opportunity. A reply carrying those headers is attached once; a reply without them becomes an unlinked activity for operator review rather than a subject-based guess.

OUT-005
Accepted outcome.

When the provider accepts a submission, one local transaction records the reviewed content and provider message ID as a timeline activity, completes the recommendation, sets the next action to awaiting response, moves the opportunity from NOW to NEXT, and creates one notification for the responsible operator. A replayed provider event repeats none of it.

OUT-006
Delivery failure.

A transient submission failure retries up to 5 times over 1 hour. A permanent failure or an exhausted retry returns the opportunity to NOW, notifies the responsible operator once, and shows the provider's reason on the message. A permanent bounce also sets the contact do-not-contact under RECORD-012.

OUT-007
Stop conditions.

A reply, a booked meeting, an unsubscribe, a do-not-contact, or a permanent bounce cancels that contact's scheduled messages and marks their unsent drafts stale under ACTION-005. A reply or a bounce ends awaiting response and returns the opportunity to NOW with the reply or the delivery problem as its next action.

OUT-008
Quiet hours.

A draft can be written at any time. Sending outside 08:00–18:00 Monday to Friday in the contact's timezone, or the workspace timezone when the contact has none, requires a second confirmation naming the recipient's local time; a scheduled send waits for the next permitted minute. Policy: outreach.quiet-hours.v1; default: the window in this clause, with no holiday calendar.

OUT-009
Scheduled send.

An operator can schedule one reviewed message for a future time and cancel it until it dispatches. Dispatch re-checks ACTION-005, RECORD-012, OUT-007, OUT-008, and OUT-010 against the current record and submits only the approved content; a stale or prohibited message is not sent, returns the opportunity to NOW, and shows the reason.

OUT-010
Sending limits.

The per-minute deployment limit and the per-operator rolling-day limit in seed.json → limits are checked before submission. A message over a limit stays unsent and visible with the limit that stopped it and the time it may be sent; Orbit neither retries it silently nor merges it with another message.

OUT-011
Unresolved submission.

Orbit records the outbound intent and its provider idempotency key durably before submitting. If the transaction in OUT-005 fails the message becomes reconciling; if the provider's response is a timeout it becomes delivery-unknown. In both states a job queries the provider by that idempotency key every 5 minutes for up to 24 hours, submits nothing again, and applies the OUT-005 outcome exactly once if acceptance is confirmed. A message still unresolved after 24 hours becomes a failure the operator can see, and notifies the responsible operator.

OUT-012
Unsubscribe.

Every outbound customer message carries List-Unsubscribe and List-Unsubscribe-Post headers handled by the mail provider. An unsubscribe event from the provider sets that contact do-not-contact under RECORD-012 within 60 seconds and cancels their scheduled messages.

AI4 clauses

AI-001
Provider and input.

Recommendation explanations and email drafts go through ai.provider.v1. The request preview shows the operator every field, timeline entry, and instruction the request will carry, and nothing outside the preview is sent.

AI-002
Output validation.

AI output must validate against its operation's schema and cite only evidence IDs present on the record. Output failing either check fails visibly and is never repaired with invented content or a semantic fallback. Only a transient transport failure is retried, at most twice within 30 seconds.

AI-003
Provider failure.

When the AI provider is unconfigured or unavailable, records, signal ingestion, linking, scoring, queue placement, search, manual updates, hand-written drafts, and sending all continue to work, and a recommendation still names its action and evidence. A generation request shows the failure and produces no explanation or draft.

AI-004
Cost.

Every AI call records provider, model, input and output tokens, feature, duration, status, and estimated cost. Operators can view totals by day and by feature in settings.

NOTIFY2 clauses

NOTIFY-001
Responsible operator.

The responsible operator for an opportunity is its owner, or, when it is unassigned, the operator whose action appears most recently on its timeline. They receive one in-app notification when it enters NOW, when a customer reply arrives on it, and when one of its outbound messages fails, bounces, or becomes delivery-unknown. When an unassigned opportunity that no operator has acted on enters NOW, every operator is notified instead. Duplicate source or provider events add no notification.

NOTIFY-002
Read state.

A notification is unread until the operator opens it or marks it read. The unread count updates within 5 seconds and never counts one event twice.

PUBLIC4 clauses

PUBLIC-001
Landing page.

GET / returns 200 without an operator session, takes its name, description, and images from ext/config.ts, and links to magic-link sign-in. It shows no contact, company, opportunity, or signal from this deployment.

PUBLIC-002
Safe demo.

When enabled in ext/config.ts and configured with the explicit PUBLIC_DEMO_OPPORTUNITY_ID binding, GET /demo/ loads one deliberately published opportunity from the dedicated hosted demo deployment after the visitor starts it. The opportunity and its observed evidence, recommendation, and publish-safe draft are created through Orbit's real operator workflow; no fixture or runtime mock is used. The visitor can edit and preview the follow-up entirely in the browser. The page states before loading and after preview that nothing is sent and no record changes. The browser makes no write request and calls no mail adapter, AI adapter, signal endpoint, or notification. The public endpoint cannot enumerate or select another record, and omits private addresses and raw signal payloads. Turning it off in ext/config.ts, or omitting the explicit binding, makes /demo and /demo/ return 404. This wording records the owner-authorized 13 September 2026 ruling that replaced the earlier browser-generated sample method while preserving its safety purpose.

PUBLIC-003
Unconfigured sign-in.

While no mail-auth adapter is configured, GET /signin returns 200 without an operator session and states that magic-link delivery is unavailable. It presents no credential field, demo account, local-login action, or session bypass.

PUBLIC-004
Native sign-in.

Configured magic-link delivery sends only to an existing active operator, gives the same request response for unknown and inactive addresses, and exchanges a hashed, single-use link within 15 minutes for a secure native session. Return locations stay inside the operator app. Sign-out revokes that session. A missing or failed mail configuration cannot issue a session.

DATA2 clauses

DATA-001
Export contents.

The export contains contacts, companies, opportunities, associations, source configuration without secrets, signals, evaluations with their policy versions, recommendations, drafts, outbound messages with their provider statuses, timeline activities, notifications, settings, and audit entries as JSON.

DATA-002
Contact erasure.

Within 5 minutes of an operator deleting a contact, their email addresses, signal payloads, drafts, message bodies, and the notifications naming them are absent from records, search results, exports, and every later AI or mail request. Only audit entries survive, with the contact's reference anonymised, as BASE-DATA-003 requires.


Baseline guarantees

22 declared clauses from this product's BASELINE.md. Selected ownership guarantees are shown below; execution evidence is separate.

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.

Declared guarantee
BASE-DATA-001
Export and import.

pnpm export produces every record and attachment; pnpm import restores it into an empty deployment; export, import, export yields an archive with equivalent contents.

Declared guarantee
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.

Declared guarantee
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.

Declared guarantee
BASE-SECRET-001
No leakage.

No secret appears in the client bundle, in logs, or in an error response.

Declared guarantee

BASELINE.md for Orbit


Release history

Honest version: there is one release line so far, and we will not invent the rest.

v0.1.0
Current — complete-workflow-implementation; acceptance requires pinned runtime and native receipts

The manifest states this version and maturity. Consult the source verification evidence before deployment.


DIY quickstart

The code is MIT and the deployment is yours. Nothing below talks to us; optional management remains planned.

Use the edition's source README for its available installation commands and required configuration.


View as agent

Everything on this page exists as machine-readable files. If you are an agent evaluating Orbit for someone, read these instead of the prose.

Installation instructions are in the source README; this entry does not declare a catalogue install command.

Catalogue endpoint

/agents/catalogue.json

Every seed with its id, category, version, clause count, install command and links to the files on the left. Generated from the seeds' own artifacts on every build, so it cannot drift from what ships.

The machine face

Orbit landing screenshot

Run Orbit on your own cloud.

MIT code, your data, your infrastructure. Leave whenever you like and it keeps running.