The fs.business() program
Author the repository-owned contract with the functional Business SDK.
The business/ folder is the contractual source of truth. Farther Shore loads
all of its supported source modules in canonical order and requires exactly one
default-exported fs.business() result.
The managed repository begins without a source file. Create
business/business.ts as the conventional starter, or split declarations into
sibling modules. Discovery is by folder, not by filename.
import * as fs from "@farthershore/business";
fs.backend("api");
const requests = fs.requests();
const status = fs.route("/v1/status", {
get: { costs: [requests.fixed(1)] },
});
fs.plan("starter", {
kind: fs.plan.kind.free,
grants: [status],
limits: [requests.perMinute(60)],
});
export default fs.business();
Functional declarations
Import the SDK as a namespace:
import * as fs from "@farthershore/business";
Start with business, route, and plan. Add measure, dimension, meter,
pricing, and meterRoutes for measured usage; requests and resource for
structural limits; backend and frontendIntegration for runtime bindings.
group composes routes and can declare custom permission subjects. Managed RBAC
enablement is operating state, not an fs.rbac() declaration.
Use the generated Business SDK exports for the complete signatures and types. The SDK guide explains how to choose and combine them.
Declarations return immutable branded refs. Pass those refs to routes, groups, and plans; do not reconstruct reference-shaped objects or join by string.
Split a growing program
Only one module may finalize the registry:
business/
business.ts # imports declarations and default-exports fs.business()
routes.ts # exports route refs
plans.ts # declares plans using imported refs
package.json
tsconfig.json
Every discovered source module executes, even when the entry module does not
import it explicitly. The normal isolated folder loader defers finalization
until all discovered modules have imported, so an alphabetically early business
module does not discard declarations in later files. Outside that loader,
fs.business() finalizes immediately and later declarations fail.
For portable, easy-to-review programs, explicitly import declaration modules
before the single default-exported fs.business() call. Do not depend on
alphabetical filenames to establish dependencies: import the refs you use.
Calling fs.business() twice is invalid even in deferred loader mode.
What folder discovery includes
Supported source extensions are .ts, .tsx, .mts, and .cts. The folder
walk skips declaration files and files named with .test/.spec suffixes, and
prunes node_modules, dist, __tests__, __fixtures__, and __mocks__.
Symlink entries are not followed by the walk. These are discovery rules, not a
sandbox for arbitrary code imported by your program.
--entry business/single-file.ts selects that file and its imports; it does not
discover all its siblings. Prefer the normal folder build when verifying what
the platform will compile. Ensure the business package uses ESM module semantics
so its default export is exposed to the loader as intended.
Contract options
fs.business() accepts these business-wide contract option families:
| Option | Responsibility |
|---|---|
visibility | Public/private business visibility intent |
authHeader | API-key header the gateway reads; default x-api-key |
upstreamAuth | Upstream-auth contract; never paste credentials into source |
billOn4xx | Business-level treatment of client-error responses for billing |
operatorPolicies | Platform operator-policy intent |
customerContext | contextTokens and customerAuth controls |
billing | Limit-upgrade timing and subscriber-change policy |
Unknown top-level options are rejected. Business identity, display name, description, icons, concrete backend origins, environment variables, and release state are platform-owned and do not belong in this call.
Determinism
Treat the program as a pure declaration graph. Do not read environment variables, make network requests, inspect the filesystem, use current time, or generate random values while declaring the contract. The compiler builds twice and rejects different hashes.
Change loop
farthershore build
farthershore validate
git add business
git commit -m "Update business contract"
git push
After push, inspect the repository validation/apply check for the same commit and intended environment. The accepted contract changes only after apply succeeds. A local build does not bind an origin, deploy your backend, or prove a subscriber can call the route.
Before handing off, exercise one allowed operation and one denied operation with a preview subscriber. Record the commit, environment, applied contract, and observed response. If compilation fails after splitting modules, check that the entry imports every declaration before sealing; if apply fails, correct the source and inspect the next apply instead of editing the generated artifact.