Seed catalogue · Sales
Ferry
An intervention-first sales pipeline for one business that turns credible deal-risk evidence into a human-controlled next move and a durable buyer commitment.
- Alternative to
- HubSpot CRM, Pipedrive, under MIT
- Family
- Sales
- Edition
- Ferry
- Version
- 0.0.0
- Contract
- 59 clauses across 15 areas
- Maturity
- prototype-contract






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
- Status
- estimate-pending-load-test
- Assumptions
- Cloudflare defaults to $0 on Workers Free for small use; external transactional mail and a domain are excluded. At the declared 10,000 active-deal limit, 15-minute INT-013 assessments create at least 960,000 D1 health-assessment row writes per day before indexes and other writes, above D1 Free's 100,000 rows-written-per-day limit. About 1,041 open deals is the theoretical Free write ceiling before indexes and other writes. Queues Free includes 10,000 operations per day; the declared 500 outbound messages per day use about 1,500 normal write/read/delete operations before retries.
- Monthly Estimate
- $0 on Workers Free for small use; D1 requires Workers Paid at the stated 15-minute assessment threshold. Estimate pending load test.
- Includes
- Workers Free baseline for small use, D1 and Queues free tiers, Cron and SQLite-backed Durable Objects including alarms
- Excludes
- external transactional mail, domain registration, custom AI providers, inbound mailbox sync, calendar sync
Externals declared
1 external, each with a reason
Under BASE-DATA-004, user data leaves only through what is declared here.
- transactional-mail
- SendGrid delivers native sign-in links through the optional Base transport. Confirmed deal-follow-up dispatch remains an unimplemented contract target.
Extension points
40 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.
Declared limits
Capacity, stated up front
Straight from seed.json → limits. Where a value is an estimate the seed says so.
- Status
- estimate-untested
- Operators
- 25
- Pipeline Stages
- 20
- Active Deals
- 10,000
- Organizations
- 10,000
- People
- 50,000
- Activities
- 250,000
- Commitments
- 100,000
- Csv Rows Per Import
- 50,000
- Outbound Messages Per Day
- 500
- Public Rate Limits
- Auth Initiations Per Ip Per Hour 5
- Auth Verifications Per Ip Per Hour 10
- Health Requests Per Ip Per Minute 60
- Asset Requests Per Ip Per Minute 600
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.
- multiple workspaces or pipelines
- role, territory, or record-visibility hierarchies
- a separate lead object
- product catalogs, quotes, invoices, and contracts
- marketing campaigns and sequences
- autonomous outbound actions
- AI scoring or general AI chat
- retrieved exchange rates or currency conversion beyond operator-recorded rates
- per-operator time zones and locales
- inbound mailbox, Gmail, Outlook, or calendar synchronization
- recurring activities
- public forms, widgets, and booking pages
- file attachments
- SMS and calling
- arbitrary report builders, custom dashboards, goals, and team forecasting
- public APIs and webhooks
- native mobile apps
- post-sale project or customer-success management
The contract
All 59 clauses of Ferry, from its own CONTRACT.md. Stable IDs identify requirements; the source handover and verification evidence distinguish implemented, tested and uncovered behavior.
HOME1 clause
/ presents the configured organization and owner name, one configured landing line, and a sign-in link. It may show the configured static Ferry credit. It contains no marketing claims, product metrics, testimonials, or telemetry.
TEAM3 clauses
Every operator can see and act on every business record. Ownership and assignment route work; they never restrict access.
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.
Settings hold one IANA business time zone and one default currency (PIPE-010). Every due time, quiet-hours window, day boundary, and Insights date range is evaluated in that time zone. Operators do not have individual time zones or individual currencies.
PIPE12 clauses
The business has one ordered set of open stages. Operators can add, rename, reorder, and retire stages; retiring a non-empty stage requires moving its open deals first. Policy: pipeline.stages.v1; default: Discovery, Qualified, Proposal, and Negotiation.
Creating a deal requires a title and at least one linked person or organization. Each open deal has exactly one stage; value, currency, expected close date, owner, and primary contact may be recorded, and any missing value is shown as Not set rather than invented.
The active board shows every open deal in its stage. Each stage shows a derived deal count and its total value under PIPE-010; each card shows title, account or contact, value, health, and an explicit next-action state of overdue, no next action, due today, or a future due time.
The default board order is overdue action, no next action, due today, then future action; ties use due time, expected close date, then deal ID. Operators can filter by owner, health, stage, and activity state without changing the records included in other operators' views.
An operator can move an open deal to any configured open stage. A stage may be configured with named exit conditions; each condition is satisfied by one recorded thing — an activity of a named type marked done, a required relationship role filled (REL-002), an open or completed customer commitment, or a manually attested fact (EVID-001). When a target stage's exit conditions are not all satisfied, Ferry names each unsatisfied condition and offers keep stage, record the missing evidence, or move anyway with a required reason. An override records the reason and the unsatisfied conditions in Deal Story and never marks a condition satisfied. Policy: deal.stage-transition.v1; default: no stage has exit conditions, so every move proceeds without a prompt. A replacement may add, remove, or change conditions; it cannot remove the override reason requirement or suppress the override record.
Marking a deal won or lost records the outcome, the actor, and the outcome time, and closes the deal (PIPE-011). Lost requires a reason. Open activities and open commitments on the deal keep their state and due times but stop producing reminders (ACT-004) and briefs (INT-001) while the deal is closed. Policy: deal.close-reason.v1; default: any non-empty free-text reason for lost, none required for won.
Changes to stage, value, currency, expected close date, owner, relationships, and outcome append an actor-attributed before/after event to Deal Story. Editing current fields never rewrites or removes those historical events.
A mutation based on a stale record version returns a conflict with the current values and changes nothing. The operator can review and deliberately reapply their edit; Ferry never silently overwrites newer work.
Every open deal records and displays four separate times, each with its own date and never merged into one number: the last recorded buyer interaction, the last recorded customer commitment, the due time of the next planned activity, and the time the deal entered its current stage. Editing a deal's fields, opening the deal, or sending an operator message changes none of them; only the underlying buyer, commitment, activity, or stage record does. Stage entry time changes only on a stage change and survives closing and reopening.
A deal's value is recorded in the business default currency (TEAM-003) unless an operator selects another ISO 4217 currency for that deal; changing a deal's currency never converts its value. Ferry retrieves no exchange rates. An operator may record a manual rate for a currency against the default. A total or ranking that spans currencies uses only operator-recorded rates, states that it is converted, and names each rate and the date it was recorded; currencies with no recorded rate are excluded from that figure and listed with their own separate totals.
Won and lost are outcomes, not stages: neither appears as a board column. A won or lost deal keeps its complete Deal Story, activities, commitments, evidence, and messages. It is excluded from the board, from Focus, and from every open-deal figure in Insights; it is included in global search (SEARCH-001), CSV export (EXPORT-001), and the portable archive. Ferry assigns no health state to a closed deal.
Reopening a closed deal requires selecting an open stage and appends a reopening event; the prior outcome, its reason, and its time remain in Deal Story. Activities and commitments suspended by PIPE-006 resume producing reminders and briefs with their original due times.
REL5 clauses
People and organizations are distinct records linked bidirectionally to their deals, activities, commitments, evidence, and messages. A person may belong to one organization and may hold one or more named roles on a deal.
Deal Story shows, for each person linked to the deal, their role, the operator who owns that relationship, and the date of the most recent recorded interaction with them. Coverage for the deal is derived as complete when every role required at the deal's current stage is filled by a linked person, gap when at least one required role is unfilled, and critical gap when a role that became required at a stage before the deal's current one is still unfilled; every unfilled required role is named. Policy: relationship.required-roles.v1; default: economic buyer and champion for every open deal, plus procurement and security reviewer from Proposal onward.
A trimmed, case-insensitive non-empty email address identifies at most one person, and a trimmed, case-insensitive name identifies at most one organization. A create or import collision surfaces the existing record and does not merge or overwrite it; similar person names, phone numbers, and similar organization names are warnings only.
Before merging two people, or two organizations, Ferry previews every field conflict and every reparented deal, activity, commitment, evidence item, person, and message. The operator chooses the surviving values; the merge applies atomically and appends an audit event, or changes nothing on failure. Merging is never performed automatically.
Operators can list people and organizations and filter them by organization, deal role, and relationship owner. Each person row shows their role, relationship owner, the date of the most recent recorded interaction, and their linked deals. Lists are paginated and state the total number of matching records; a displayed count never disagrees with the set it summarises.
ACT4 clauses
A call, meeting, task, email follow-up, or deadline has a subject, owner, due time evaluated in the business time zone (TEAM-003), and links to a deal plus optional people and organization. Its stored state is planned, done, or cancelled; overdue is derived when a planned activity's due time passes.
Completing an activity records the actual completion time once and preserves its original due time. Repeating the completion operation is a no-op. Completion prompts the operator to create a next activity or record why none exists, but never creates one or changes deal health by itself.
Operators can list and filter activities by overdue, today, future, owner, type, and linked deal. Completing, rescheduling, cancelling, or reassigning an activity updates the relevant queue immediately while its prior state remains in Deal Story.
In-app reminders appear when a planned activity becomes due and again when it becomes overdue. Email reminders are opt-in and are sent within 5 minutes of that transition, or within 5 minutes of the end of quiet hours if the transition falls inside them. A reminder is sent once per due-state transition and is cancelled when the activity is completed, cancelled, rescheduled, or reassigned. An operator-initiated send (MAIL-001) is never delayed by quiet hours. Policy: activity.reminder.v1; default: in-app reminders on, email reminders off, quiet hours 19:00 to 08:00 in the business time zone.
COMMIT4 clauses
A customer commitment belongs to one deal and records a named customer person, a concrete promised outcome, a due time, the operator who recorded it, and either a linked source event or an explicit manual attestation. An internal task or an operator's own promise is not a customer commitment.
A commitment is open, completed, or cancelled; overdue is derived when an open commitment's due time passes. Completing, revising, or cancelling one appends the actor, time, and prior values; revisions never rewrite the original promise.
The same commitment record appears in Focus, Deal Story, the daily work queue, and Insights. Updating it in any surface produces the same resulting state everywhere.
Repeating the same completion, cancellation, or revision request produces no duplicate event and no second health assessment.
EVID2 clauses
A fact is an attributable, timestamped record of a customer or operator event. Every fact shown in an Intervention Brief links to its source event; manually recorded facts identify their recorder and are labelled manual.
An inference is stored and displayed separately from facts, names the facts it relies on, and can be corrected or dismissed without altering those facts. Inferred content is never presented as customer confirmation.
STORY2 clauses
Deal Story presents the current commercial fields, relationships, commitments, facts, inferences, activities, outbound messages, health assessments, and attributed history for one deal in chronological order.
Correcting a current field, manual fact, or inference appends the correction and actor to Deal Story. Source events and previously issued health assessments remain visible as historical context.
INT13 clauses
After sign-in, Focus opens as a projection over canonical deal records, not a separate task store. It shows one expanded Intervention Brief and no more than the next two ranked briefs; a healthy queue states when no intervention needs action and still shows today's commitments.
Every open deal has exactly one current state — On track, Watching, Slipping, At risk, or Not actionable — and a rationale linked to the contributing records. The states are evaluated in this order, and every open deal matches one. Not actionable is set by an operator under INT-007. Otherwise, by default: Slipping means an open commitment or the next planned activity is overdue; At risk means Slipping with an expected close date inside 30 days and a credible intervention available (INT-011); On track means nothing is overdue, the deal has an open qualified commitment, and a planned next activity is due no later than that commitment; Watching is every remaining open deal — nothing is overdue, but a stage exit condition (PIPE-005) or required relationship role (REL-002) is unfilled, or the deal has no open qualified commitment, or it has no planned next activity. Record-update time alone never changes health. Policy: deal.health-assessment.v1; default: the conditions above. A replacement may change those conditions and thresholds but may not add a state outside this list, may not leave an open deal without a state, and may not make an outbound message, a record edit, or elapsed time alone produce On track (INT-008).
Focus ranks active briefs by recoverable deal value (PIPE-010), evidence of broken buyer momentum, time sensitivity, and whether a credible intervention exists; it displays those four factors instead of a percentage score. Equal briefs sort by earliest commitment or activity due time, then deal ID. Policy: intervention.ranking.v1; default: the four factors above, ordered so that a brief with a credible intervention always outranks one without.
An expanded brief shows impact, why now, the four time signals from PIPE-009, two to four cited facts or labelled inferences, one recommended action with its intended outcome and the source named under INT-011, controls, and the qualified buyer commitment that would demonstrate progress.
Missing or conflicting evidence produces Cannot recommend safely, names the missing or conflicting inputs, and offers only record correction, evidence capture, or Deal Story navigation. Ferry never fabricates evidence, a recommendation, or a recipient to fill a gap.
A prepared email, call, or task is editable. An operator may switch action, revise recipients or content, abandon it, or explicitly confirm it. Ferry never sends a message, creates an activity, or completes an activity without an explicit operator confirmation; no policy, extension, or setting enables autonomous sending or autonomous record changes.
Deferring a brief requires a reason and a revisit time. Marking a deal Not actionable requires a reason and one next disposition — re-qualify, move the expected close date, nurture, reassign the deal to another operator, or close lost. Neither choice removes the record or its history.
Sending or scheduling a follow-up appends its action records but does not improve deal health. Only a commitment satisfying COMMIT-001, together with the next activity required by INT-002, may produce a new On track assessment.
At most one active brief exists for the same deal and causal evidence set. Re-evaluating or redelivering the same evidence updates that brief instead of creating another; materially different evidence may create a new brief and supersedes any now-stale recommendation.
If health or intervention evaluation fails, canonical deals, activities, and commitments remain usable and no prepared action is dispatched. An affected brief shows its last successful evaluation time and a visible failure. When no evaluation has succeeded for 30 minutes, Focus shows a stale-evaluation warning with that time above the queue, whether or not any brief exists. A successful re-evaluation clears the warning without erasing the failure from operations history.
The recommended action in a brief is produced from the deal's own records, and the brief names the built-in playbook that produced it and the records it used. Playbooks are part of the recommendation policy, not an operator-editable object. Policy: intervention.recommendation.v1; default: playbooks for a missed customer commitment, an unfilled required role, no recorded buyer interaction since the deal's last outbound message, and an expected close date that has passed or falls within 7 days with no planned next activity.
Ferry calls no AI provider and declares none in seed.json → externals; no content is labelled or presented as AI-generated. No number shown to an operator is a score: every health state, ranking factor, coverage state, and Insights figure names the records or the formula it derives from.
A deal's health is recalculated within 5 seconds of a change to its stage, value, expected close date, relationships, activities, commitments, or evidence, and for every open deal at least every 15 minutes so that a due time passing changes health with no record change. Each assessment records the time it ran and the records it used.
MAIL4 clauses
Confirming Send and schedule transactionally creates one outbound message and one linked next activity before dispatch. If that transaction cannot commit, neither is created and no provider request is made. The provider request is made within 60 seconds of confirmation through mail.sender.v1; only the confirmed recipients and content leave the deployment.
An outbound message is draft, queued, accepted, or failed. The UI says sent only after the provider accepts the message; a later rejection or bounce changes it to failed and shows the provider reason without changing deal health.
Double-clicks, client retries, queue redelivery, and provider callback replay cannot create or send a second message. Every attempt reuses the message's stable ID as its idempotency key.
Transient provider failures retry up to five times over one hour. A terminal failure remains visible on the message and its linked activity with a deliberate retry action; retry reuses the original message ID and never hides the failed attempt.
SEARCH1 clause
Global search matches deal titles, organization and person names, person emails, activity subjects, commitment text, and message subjects, across open and closed deals, and returns within 500ms. Each result identifies its type and whether its deal is closed, and opens the canonical record.
IMPORT3 clauses
CSV import accepts one entity type per file — deals, people, organizations, or activities. It maps columns and validates every row before confirmation, showing creates, ID-based updates, collisions under REL-003, warnings, and rejected rows with their original row numbers and specific reasons. A file at the row limit in seed.json is previewed within 60 seconds.
A confirmed import processes each row transactionally and reports accepted and rejected counts without silent skips. Each attempt has a durable ID and records the file's checksum; the file itself is not retained. Retrying an attempt requires re-uploading a file with the same checksum and continues that attempt rather than producing a second result; a different checksum starts a new attempt.
An Ferry ID updates that record. Without an ID, a deal row creates a deal and title similarity is only a warning; person and organization collisions follow REL-003. Imported values never overwrite an existing person or organization automatically.
INSIGHT3 clauses
Insights shows open commitments due, active interventions, and recoverable revenue. Recoverable revenue is the recorded value of open Slipping or At risk deals that have an active Intervention Brief, reported under PIPE-010; the UI exposes the formula, filters, date range, and records included.
Every commitment, intervention, health, and revenue row opens the corresponding Deal Story or Intervention Brief with the same filters preserved on return.
A metric shows a change against an earlier period only when Ferry holds the stored records for that period; the comparison names its window and opens the records behind both values. A metric with no stored prior period shows its current value and no trend. Every headline figure agrees with the rows the same view lists beneath it.
FIELD1 clause
Operators define custom fields on deals, people, organizations, and activities in settings, each with a name and type. Values appear on the record and in Deal Story, and travel through CSV export and import (EXPORT-001, IMPORT-003). Removing a field definition hides it from entry forms and keeps every recorded value in Deal Story and in exports until an operator deletes it.
EXPORT1 clause
In addition to the complete portable archive required by BASE-DATA-001, operator CSV exports include stable Ferry IDs, linked-record IDs, custom fields, stage and outcome history, original activity due times, actual completion times, and commitment states, so that an edited export can be reimported as deterministic updates.
Baseline guarantees
22 declared clauses from this product's BASELINE.md. Selected ownership guarantees are shown below; execution evidence is separate.
The deployment makes no request to the marketplace or the seed author. There is no telemetry, phone-home, licence check, or kill switch.
pnpm export produces every record and attachment; pnpm import restores it into an empty deployment; export, import, export yields an archive with equivalent contents.
User data leaves the deployment only through externals declared in seed.json → externals. No other outbound request carries user data.
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.
No secret appears in the client bundle, in logs, or in an error response.
Release history
Honest version: there is one release line so far, and we will not invent the rest.
- v0.0.0
- Current — prototype-contract
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 Ferry for someone, read these instead of the prose.
Installation instructions are in the source README; this entry does not declare a catalogue install command.
- README.md
- Source setup, available commands and implementation status.
- seed.json
- The manifest: capabilities mapped to clauses, externals, extension points, limits, operating cost, deploy requirements.
- CONTRACT.md
- The 59 clauses above, in source form.
- BASELINE.md
- The product's declared baseline requirements.
- AGENTS.md
- Instructions written for the coding agent that will maintain this deployment.
- /llms.txt
- The site, for machines.
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.

Run Ferry on your own cloud.
MIT code, your data, your infrastructure. Leave whenever you like and it keeps running.