PF research library · 6 min read
PF Simulation SaaS: external integrations
r34 documentation · hosted-integrations.md · Formatted reading copy
On this page
The hosted edition supplies real provider adapters with explicit configuration. The release tests their request/response contracts using controlled doubles. It has not provisioned AWS resources, sent an external email, authenticated a real Cognito account or processed a live payment. Those checks require the operator's configured accounts. The standalone scientific edition imports none of these adapters and continues to run without a SaaS account.
Private results and input storage
PF_SAAS_STORAGE_BACKEND=local uses a private directory outside the web document
root. Local storage is designed for Linux/POSIX; Windows users can run the SaaS
edition through the supplied Linux containers. Every key is a relative POSIX
path. Traversal, absolute paths, control characters and symlinks are rejected.
Files are written atomically with owner-only permissions. SaaS services authorize
the organization and project before opening a stored object.
PF_SAAS_STORAGE_BACKEND=s3 uses PF_SAAS_S3_BUCKET,
PF_SAAS_S3_PREFIX and PF_SAAS_AWS_REGION. Optional
PF_SAAS_S3_KMS_KEY selects KMS encryption; otherwise uploads request SSE-S3.
The service obtains credentials from the standard AWS credential chain, including
the task's IAM role. Do not place access keys in browser configuration. The AWS
deployment configures private buckets and block-public-access settings. Storage
adapters do not assign public ACLs or return anonymous object links; downloads
pass through the application's authorization checks.
The stored numerical artifacts retain complete complex density matrices and provenance. Cloud storage does not recalculate or simplify scientific results.
Accounts and email
Local accounts use verified email addresses and server-side sessions. In
PF_SAAS_MAIL_MODE=outbox, messages are written to data_dir/outbox for a local
developer or operator to inspect. The response says delivered: false; the
application does not pretend to send them. This mode is refused in production.
Outbox files contain one-time account links and must remain private.
For actual SMTP delivery, select PF_SAAS_MAIL_MODE=smtp and configure
PF_SAAS_SMTP_HOST, PF_SAAS_SMTP_PORT, PF_SAAS_SMTP_FROM, and any required
PF_SAAS_SMTP_USERNAME and PF_SAAS_SMTP_PASSWORD. Choose STARTTLS with
PF_SAAS_SMTP_STARTTLS=true or implicit TLS with PF_SAAS_SMTP_SSL=true and
STARTTLS false. Production requires encrypted SMTP transport. A successful SMTP
response means the mail server accepted the message; recipient delivery still
depends on the mail provider and domain configuration.
Optional Cognito mode uses PF_SAAS_AUTH_MODE=cognito,
PF_SAAS_COGNITO_REGION, PF_SAAS_COGNITO_USER_POOL_ID,
PF_SAAS_COGNITO_CLIENT_ID and the hosted login domain
PF_SAAS_COGNITO_DOMAIN. The server checks the RS256 signature against the
configured pool's JWKS, exact issuer and client audience, expiration, issued-at,
subject, token_use=id, and verified email. Provider identities are keyed by
issuer and subject. Possession of an email string does not authorize linking an
existing local account. The account module supplies the browser authorization
code/PKCE flow and exchanges the verified identity for the application's
HttpOnly session cookie.
Subscription plans and entitlements
Billing is disabled by default. Accounts use the configured Starter limits; the UI does not invent subscription prices or a payment connection.
Set PF_SAAS_BILLING_MODE=stripe, PF_SAAS_STRIPE_SECRET_KEY,
PF_SAAS_STRIPE_WEBHOOK_SECRET, PF_SAAS_STRIPE_PRICE_RESEARCH and
PF_SAAS_STRIPE_PRICE_TEAM to enable the adapter. The two configured price IDs
must be distinct. Create the corresponding recurring prices and configure the
Stripe customer portal in the provider account before offering paid checkout.
Prices, currency, tax behavior, trial policy and payment methods belong to that
provider configuration. No browser-supplied price ID or payment amount is used.
The initial server-owned quota policy is:
| Plan | Per-job time | Concurrent jobs | Queued jobs | Monthly compute | Storage |
|---|---|---|---|---|---|
| Starter | Base | Base | Base | Base | Base |
| Research | Base | 2 × base | 2 × base | 4 × base | 4 × base |
| Team | Base | 4 × base | 4 × base | 12 × base | 12 × base |
Base values are the deployment's max_job_seconds, max_concurrent_jobs,
max_queued_jobs, monthly_compute_seconds, and max_storage_bytes settings.
The API and worker must use matching base settings. The operator should choose
these allowances to match measured capacity and the published commercial offer.
They limit admitted work; they never reduce quantum fidelity or generate
substitute simulation results. Worker resources are controlled separately by
the fixed task/container definition.
Configure the webhook at /api/billing/webhook for
customer.subscription.created, customer.subscription.updated,
customer.subscription.deleted, checkout.session.completed,
checkout.session.expired, and checkout.session.async_payment_succeeded.
It verifies an HMAC over the raw body and a timestamp within five minutes,
records processed event IDs, and retrieves current subscriptions before changing
entitlements. Repeated or out-of-order event payloads cannot alone restore a
canceled subscription. Provider outages return an error so delivery can retry.
Monitor failed webhook deliveries; an administrator can request reconciliation
through the endpoint below after restoring the connection.
Active/trialing subscriptions receive the matching plan. Past-due, unpaid,
paused or invalid subscription states block new compute admission. Cancellation
returns to Starter limits while existing authorized results remain accessible.
An administrator may grant a plan separately, with a recorded reason. Such a
grant reports source=administrator, status=manual; it is not recorded or
presented as a paid subscription and can be removed explicitly.
| Endpoint | Required access | Purpose |
|---|---|---|
GET /api/billing/plans |
Signed in | Plans, quota policy and checkout availability |
GET /api/billing?org_id=… |
Organization viewer | Effective plan, limits and integration status |
POST /api/billing/checkout |
Organization admin/owner, CSRF | {org_id, plan_id} → hosted checkout URL |
POST /api/billing/portal |
Organization admin/owner, CSRF | {org_id} → hosted billing portal URL |
POST /api/billing/webhook |
Valid provider signature | Idempotent subscription synchronization |
PATCH /api/admin/organizations/{id}/entitlements |
Platform admin, CSRF | {plan_id, reason}; null removes the override |
POST /api/admin/organizations/{id}/billing/reconcile |
Platform admin, CSRF | Recover current provider subscription state |
Payment credentials are needed only by the API. A worker can keep
PF_SAAS_BILLING_MODE=disabled: it still enforces the persisted subscription and
administrator entitlements without calling Stripe.
AWS job execution
PF_SAAS_EXECUTION_BACKEND=aws_batch selects a fixed
PF_SAAS_AWS_BATCH_QUEUE and PF_SAAS_AWS_BATCH_JOB_DEFINITION in
PF_SAAS_AWS_REGION. The deployment owns the image, task role, database
connection, storage permissions and resource allocation. Job submissions can
supply only validated application job, attempt and lease identifiers. They
cannot replace the image, role, command, queue or environment.
The adapter invokes python -m pf_saas.worker --job-id … --attempt-id … --lease-token …. Batch automatic retries are disabled; failed attempts are
visible and application retries are explicit. The database fences duplicate
executors for an attempt. A Batch SUCCEEDED status alone does not mark a
scientific run successful: the worker must commit its real outputs and finish
its application lease. Cancellation terminates running tasks and cancels those
that have not started. Continuous tracking is executed as explicitly bounded
jobs under the selected resource policy.
Verification scope and source references
test_saas_cloud.py covers private local file round trips and traversal/symlink
rejection; S3 encryption request parameters; explicit development outbox and
SMTP request contracts; Stripe fixed-price checkout, authenticated webhooks,
idempotency, out-of-order reconciliation and tenant boundaries; manual grant
auditing; RSA Cognito claim rejection; the fixed AWS task command; and billing
HTTP authorization and CSRF checks. External adapters are doubled in these
tests, not live-connected.
Production activation additionally needs actual provider configuration and
verification of redirects, mail delivery, webhook delivery, task startup,
network access, IAM permissions, storage encryption, recovery and costs. See
SAAS_DEPLOYMENT.md for the deployment procedure and its separate validation
record.
Primary interface references: