Skip to main content

cratefield_core/
lib.rs

1//! `cratefield-core` is the runtime-agnostic kernel of the Factory Zero harness:
2//! the [`Module`] contract, the [`Harness`] builder, port traits, RFC 9457
3//! problem+json errors, the request [`Scope`], an in-process [`EventBus`] and
4//! a [`TemplateRegistry`] (ADR 0001, 0002, 0007).
5//!
6//! Core depends only on `http`, `axum` (default features off), `serde`,
7//! `tracing`, `sea-query` and pure-Rust crypto. It must never depend on
8//! `worker`, `wasm-bindgen`, `tokio`, `reqwest`, `sqlx` or `rusqlite`, and
9//! never touches `std::fs` or `std::net` — CI enforces this with a
10//! `cargo tree` check and the wasm build of `examples/venture`.
11
12#![doc = include_str!("../README.md")]
13#![forbid(unsafe_code)]
14
15mod admin;
16mod api_key;
17mod classifier_agreement;
18mod classifier_routing;
19mod config;
20mod cooldown;
21mod cost;
22mod csv;
23mod email;
24mod events;
25mod harness;
26mod http;
27mod idempotency;
28mod lint;
29mod logging;
30mod module;
31mod origin;
32mod outbox;
33mod personal_data;
34mod ports;
35mod problem;
36mod problems;
37mod rate_limit;
38mod route_policy;
39mod scheduled;
40mod scope;
41mod sidecar;
42mod signer;
43// The provider-neutral billing lifecycle (issue #593): the names are
44// generic, so the module is public and namespaced as `billing::`.
45pub mod billing;
46// The `Blob` port's presigned URLs (issue #622); pure `SigV4`, public so
47// adapters and tests share one implementation.
48pub mod sigv4;
49mod stream;
50mod structured_output;
51mod surface;
52mod template;
53mod tenant;
54mod tenant_conn;
55mod tenant_lifecycle;
56mod tool_loop;
57mod usage;
58mod venture;
59mod webhook_signature;
60
61// `Module::router` returns an `axum::Router` and `well_known` an
62// `Option<axum::Router>`, so a module author cannot implement the trait
63// without axum — and an out-of-tree one has no workspace to inherit the
64// version from. Picking a semver-incompatible one gives a type error
65// about two `Router`s that look identical, which is a bad afternoon.
66// Re-exported so there is one axum and it is this crate's.
67pub use axum;
68
69pub use admin::{bearer_token, constant_time_eq, require_admin};
70pub use api_key::{
71    ApiKeyError, ApiKeyMode, ApiKeyPrincipal, ApiKeys, IssuedKey, RandomBytes, RandomError,
72    require_api_key,
73};
74pub use classifier_agreement::{
75    AgreementAt, AgreementLog, AgreementReport, CalibrationPoint, CorpusItem, Disagreement,
76    GroundTruth, KindAgreement, answer_margin, measure_agreement, values_agree,
77};
78pub use classifier_routing::{
79    RouteReason, Routed, RoutingClassifier, RoutingError, RoutingMode, RoutingPolicy,
80    ShadowClassifier, Thresholds,
81};
82pub use config::{Config, ConfigError, EmptyConfig, HarnessConfig, MapConfig, ModuleConfig};
83pub use cooldown::SendCooldown;
84pub use cost::{
85    Accounting, AdapterId, CallOutcome, CallRecord, CallRole, Cost, CostLedger, InMemoryLedger,
86    LedgerTotals, Price, PriceSheet, QuestionKind, TokenSource, Tokens,
87};
88pub use csv::{FORMULA_PREFIXES, MAX_EXPORT_ROWS, escape as csv_escape, row as csv_row};
89pub use email::{
90    MAX_EMAIL_BYTES, MAX_LOCAL_BYTES, invalid_email_problem, is_valid,
91    normalize as normalize_email, validation_error,
92};
93pub use events::{AnyError, EventBus, EventHandler, EventName};
94pub use harness::{Harness, HarnessBuilder, Runtime};
95pub use http::{
96    Form, Json, MAX_BODY_BYTES, RequestSummary, X_REQUEST_ID, allowance_exhausted, rate_limited,
97    request_id_is_valid,
98};
99pub use idempotency::Inbox;
100pub use lint::{CARD_DATA, card_data_hit, created_tables, lint_card_data, lint_portable_sql};
101pub use logging::{
102    ControlLevel, RedactingVisitor, forward_control_event, is_email_field, is_secret_field,
103    redacted_value, scrub_request_url, scrub_text, set_error_forwarder, set_log_pseudonym_key,
104    subject_hash,
105};
106pub use module::{
107    BoxFuture, HARNESS_API, Migrations, Module, ModuleContext, SqlMigration, assert_migration_set,
108    harness_api_mismatch, is_idempotent_sql, migration_checksum, migration_edited,
109    migration_missing_guard,
110};
111pub use origin::{OriginError, origin_of};
112pub use outbox::{DrainOptions, DrainReport, Outbox, OutboxRecord, Processed};
113pub use personal_data::{
114    CatalogEntry, DataKind, Disposition, PersonalDataCatalog, PersonalDataSet, SubjectVia,
115    is_plain_identifier, migration_tables, undeclared_tables, unlisted_tables,
116};
117pub use ports::{
118    ACTOR_CALL_TIMEOUT, ActorContext, ActorError, ActorHandler, ActorHandlers, ActorStore,
119    ActorWrites, Actors, Answer, AnswerValue, Auth, AuthError, Blob, BlobError, BlobObject,
120    BoundedHttpClient, Calibration, Caller, Capability, Captcha, CaptchaBinding, CaptchaError,
121    CertificateStatus, Charge, CheckoutRequest, CheckoutSession, Classifier, ClassifierError,
122    ClassifierProfile, Clock, Completion, ConnectAccountLink, ConnectAccountLinkRequest,
123    Credential, CustomHostname, CustomHostnameError, CustomHostnames, DEFAULT_MAX_STATE_CHARS,
124    DEFAULT_MAX_TOKENS, DEFAULT_RESPONSE_TIMEOUT, Database, DbError, Decision, Defer, Destination,
125    DispatchError, Dispatcher, DnsRecordType, EmbedError, Embedder, Embeddings, ExactVectorIndex,
126    Filed, HostnameClaim, HostnameRefusal, HttpClient, HttpError, HttpPolicy, IdGen, ImageLimit,
127    ImageMediaType, InboundStatusError, KeyValue, Kid, KvError, LineItem, LocKeys,
128    MAX_ACTOR_KEY_BYTES, MAX_ACTOR_KIND_BYTES, MAX_ACTOR_MESSAGE_BYTES, MAX_ACTOR_REPLY_BYTES,
129    MAX_ACTOR_VALUE_BYTES, MAX_BLOB_BYTES, MAX_CONCURRENT_REQUESTS, MAX_IMAGE_ENCODED_BYTES,
130    MAX_KID_NAME, MAX_NAMESPACE_BYTES, MAX_PROMPT_IMAGE_ENCODED_BYTES, MAX_PROMPT_IMAGES,
131    MAX_RESPONSE_BYTES, MAX_RESPONSE_TIMEOUT, MailError, Mailer, Member, Message, ModelTier, Money,
132    NoopDefer, Notification, Part, Payload, Payments, PaymentsError, Platform, Port, Ports,
133    Priority, Prompt, ProviderStatus, Push, PushError, PushOutcome, Question, Quota,
134    RateLimitError, RateLimiter, Realtime, RealtimeError, Recipient, Refund, RefundRequest, Role,
135    RoomContext, RoomHandler, RoutingPush, RoutingTextModel, RoutingTracker, Row, Rows,
136    ScopedActors, ScopedBlob, SendOutcome, Severity, SignatureError, Signer, Statement, StatusOnly,
137    StatusUpdate, StatusWebhook, Subject, SubscriptionCheckoutRequest, SystemClock, TextModel,
138    TextModelError, TicketComment, TicketDraft, TicketState, TicketStatus, ToolCall, ToolChoice,
139    ToolResult, ToolSpec, Tracker, TrackerError, TransferCharge, TryFromValue, Turn, UlidIdGen,
140    Unconfigured, UsageReport, UsageReported, Validation, ValidationMethod, VectorFilter,
141    VectorIndex, VectorIndexError, VectorMatch, VectorNamespace, VectorRecord, Verdict,
142    WebhookEvent, check_actor_call, check_blob_size, check_hostname, declared_content_length,
143    encode_image, encoded_image_len, receive_status, retry_after, run_actor_alarm,
144    run_actor_message, timeout, ttl_secs, validate_actor_key, validate_actor_kind,
145    validate_questions,
146};
147// The dispute, portal and subscription types on `Payments` (issues #589,
148// #602, #690).
149pub use ports::{
150    Dispute, DisputeListRequest, DisputePage, DisputePhase, DisputeStatus, PortalSession,
151    PortalSessionRequest, Subscription, SubscriptionStatus,
152};
153// The Blob presign API (issue #622), kept out of the wholesale block above.
154pub use ports::{DEFAULT_PRESIGN_TTL, MAX_PRESIGN_TTL, PresignedPut};
155// The inbound mail source (issue #563), kept out of the wholesale block
156// above so that block stays untouched.
157pub use ports::{InboundMailError, InboundMailSource, InboundMessage, receive_mail};
158// The Blob streamed reads/writes and multipart API (issue #586), kept out
159// of the wholesale block above for the same reason.
160pub use ports::{
161    BlobMeta, BlobPage, BlobStream, MAX_LARGE_BLOB_BYTES, MAX_LIST_LIMIT, MAX_MULTIPART_PARTS,
162    MIN_MULTIPART_PART_BYTES, PartReceipt, PendingUpload, UploadId, blob_error_from_stream,
163    check_part_number, limit_stream,
164};
165pub use problem::{ABOUT_BLANK, Problem};
166// `Slugs` is exported beside the `SLUGS` value it types. Without it a
167// caller can read `SLUGS.validation_failed` and cannot write a function
168// that takes the table — the value was reachable and its type was not
169// nameable, which `unnameable_types` is what noticed.
170pub use problems::{ProblemDef, SLUGS, Slugs, registry as problem_registry};
171pub use rate_limit::{RateLimit, RateLimitFailure, check_rate_limit, client_ip, rate_limit_keys};
172pub use route_policy::{
173    ALLOW_UNLIMITED_PUBLIC_ROUTES, ALLOW_UNPROTECTED_WRITES, RoutePolicy, SignatureVerification,
174    WriteGuards, captcha_effective, deployed_env, env_disagreement, payments_effective,
175    production_readiness, rate_limiter_effective, signer_effective, stated_reason,
176    unlimited_public_routes_override, unprotected_writes_override, verify_human_form,
177    webhook_secret_readiness,
178};
179pub use scheduled::{ScheduledBudget, ScheduledLimits, ScheduledSplit};
180pub use scope::Scope;
181pub use sidecar::{
182    GATEWAY_ADMIN_PURPOSE, GATEWAY_PURPOSE, GATEWAY_TOKEN_TTL_SECS, HARNESS_ONE_WORKER,
183    HARNESS_SIDECARS, SIDECAR_GATEWAY_SECRET, SIDECAR_REQUIRE_GATEWAY, SidecarMount, SidecarMounts,
184    X_HARNESS_API, X_HARNESS_GATEWAY, X_HARNESS_MODULE,
185};
186pub use signer::{
187    CONFIRM_TOKEN_MAX_TTL_SECS, DEFAULT_TOKEN_MAX_TTL_SECS, HmacSigner, KeyRing, KeyState,
188    MIN_SECRET_BYTES, RingKey, STATUS_TOKEN_MAX_TTL_SECS, SignerError, TokenPolicy,
189    UNSUBSCRIBE_ACTION,
190};
191pub use stream::{BoxStream, RequestStream, ResponseStream, StreamError, StreamRoute};
192pub use structured_output::TextModelExt;
193pub use surface::{
194    Action, Audience, Column, HINT_KEYWORDS, MAX_SIDECAR_ACTIONS, MAX_SIDECAR_SURFACE_BYTES,
195    MAX_SIDECAR_VIEWS, ModuleSurface, Outcome, RenderedSurface, SURFACE_API, Surface,
196    SurfaceDocument, SurfaceSource, UiContext, UiMount, VentureSurface, View, hint_field,
197    schema_for,
198};
199pub use template::{Rendered, Template, TemplateError, TemplateRegistry};
200pub use tenant::{
201    IMPLICIT_TENANT, ImplicitTenant, Resolution, ResolveTenant, Tenancy, Tenant, TenantDatabases,
202    TenantDbError, TenantId, TenantRouting, TenantStatus,
203};
204pub use tenant_conn::TenantConn;
205pub use tenant_lifecycle::{
206    ErasureStep, TenantLifecycle, TenantLifecycleError, TenantSummary, remaining_erasure,
207};
208pub use tool_loop::{
209    StepUsage, ToolBudget, ToolExecutor, ToolLoopError, ToolLoopOutcome, run_tool_loop,
210};
211pub use usage::{Consumed, Consumption, Exhausted, Months, Period, PeriodWindow, Usage};
212pub use venture::{Brand, Venture, VentureEnv};
213pub use webhook_signature::{
214    DEFAULT_TOLERANCE_SECS, Digest, Github, Gitlab, ProviderScheme, SharedTokenScheme,
215    SignatureEncoding, SignatureScheme, SignedDelivery, StripeStyle, Svix, Vercel, WebhookVerifier,
216    svix_secret_key,
217};