The S3-compatible connector (AWS S3, Cloudflare R2, MinIO) is fully wired into the
REST API: create a connection once, then test, validate, and forecast against it.
Connection-management calls require a tenant identity (an API key with an
organization, or an
EOMER_API_KEY_TENANT_MAP_JSON mapping for local keys).What a connector gives you
A data connection is a tenant-owned, reusable pointer to your data system, with credentials handled securely on eomer’s side. Once configured, eomer can:- Test connectivity and authentication (
test_connection) - Discover objects under a prefix (
list_objects) and estimate volume (estimate_size) - Infer schema from a bounded sample (
infer_schema) - Validate the data as a forecasting dataset (
validate_source) - Read the data for a forecast job (
read_data) - Write forecast results back to a destination (
write_output)
Credential model (IAM-first)
| Auth method | Secret stored? | Use when |
|---|---|---|
sts_assume_role | No | Recommended for AWS — you grant eomer’s AWS identity sts:AssumeRole on a read-only role (role_arn + external_id on the connection); eomer uses short-lived STS credentials. |
iam_role, instance_profile, workload_identity | No | Same-account / workload-identity setups. |
access_key | Yes — envelope-encrypted | Cloudflare R2, MinIO, or S3 without role access. |
sas_token, service_account_json | Yes — envelope-encrypted | Reserved for Azure / GCS in a later phase. |
EOMER_CONNECTOR_ENCRYPTION_KEY before persistence. API responses never
return secrets — only a redacted summary (auth_method, a masked hint, key
version). See the package README.md for rotation and the KMS path.
REST quickstart
credential summary
(auth method, masked key hint, key version).
Configure an S3-compatible source (Python library)
AWS S3 (keyless)
Cloudflare R2
R2 is S3-compatible, so it reuses the same connector — only the endpoint, region, and (sealed) access key differ:Validate before you forecast
validate_source reuses eomer’s core validator (required columns, null checks,
numeric target, duplicate entity-time rows, parseable timestamps, minimum
history) and adds frequency inference, schema-drift detection, and a volume
guardrail.
Deliver results back to your system
Add anoutput block to the forecast request and eomer writes the completed
forecast straight back to your bucket — closing the loop with no polling or
manual download:
output.connection_idmay point at a different connection (it must belong to your tenant); omitted = write back to the source connection.key_templatesupports{job_id}and{date}placeholders; the default iseomer-forecasts/{date}/{job_id}.csv. Formats: csv, json, jsonl, parquet.- Delivery never overwrites existing objects unless
allow_overwrite: true. - Track it on the job:
GET /jobs/{job_id}returnsdelivery_status(pending → delivering → delivered | failed | skipped),delivery_uri, and a sanitizeddelivery_error. A failed delivery never fails the forecast — the result stays downloadable and the attempt is recorded in the audit trail (action: "deliver").
Partitioned data, globs, and compression
- A trailing-slash
prefixreads and concatenates all objects under it; addkey_pattern(e.g."part-*.csv","2026-*/part-*.parquet") to filter. - Set
compression: "gzip"on the connection for gzip’d CSV/JSON objects (zstdsupported with the optionalzstandardpackage); Parquet’s internal codec needs no configuration. - Forecast submission returns 202 immediately — the connector read happens
inside the job worker, and a failed read marks the job
failedwith the sanitized connector error (visible onGET /jobs/{job_id}and in the audit trail).
Safety guarantees
- Reads are byte- and row-bounded (
max_bytes/max_rows) — oversized sources raiseDATASET_TOO_LARGEinstead of OOMing. - Object keys are sanitised against path traversal and control characters.
- Format magic bytes are checked (a Parquet file declared as CSV fails fast).
- Writes refuse to overwrite existing objects unless explicitly allowed, and can apply server-side encryption.
- Every failure maps to a stable
ConnectorErrorCode(AUTHENTICATION_FAILED,AUTHORIZATION_FAILED,SOURCE_NOT_FOUND,RATE_LIMITED, …); provider error text is never echoed back.