2026-09-30 23:06:07 +00:00
2026-09-30 23:06:07 +00:00
2026-09-30 23:06:07 +00:00
2026-09-30 23:06:07 +00:00
2026-01-26 08:24:23 +00:00
2026-01-26 08:24:23 +00:00
2026-09-30 23:06:07 +00:00

@fin.cx/docbox

Open-source, self-hosted document intake and management for organizations.

Docbox takes in documents — invoices, receipts, contracts, letters, statements — files them, extracts their text, finds exact duplicates and keeps them searchable and shareable for the members of an organization. People sign in through idp.global; Docbox has no accounts or passwords of its own. Document metadata lives in a MongoDB-compatible database, the files themselves in S3-compatible object storage, and the web app updates live as documents change.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

Features

  • Sign-in through idp.global. OIDC authorization code with PKCE, an HttpOnly cookie session with a CSRF token, and roles taken live from idp.global organization memberships. Membership is checked at idp.global on every request; a confirmed one is reused for DOCBOX_AUTHORITY_CACHE_SECONDS.
  • Organizations. Every document, scan, entity, project, process, share and processing job belongs to exactly one organization, and one tenant scope narrows every read and write to the session's organization. Each organization is linked to one idp.global organization. The instance operator creates and links organizations but never sees their documents.
  • Library. Inbox (the review queue), Flagged, Recent, All and Archive, with stable scope counts, facet filters (type, source, entity, tag), server-side search, review, flagging, archiving and bulk actions.
  • Rich metadata with provenance. Type, language, parties, amounts, currency, references, due dates, periods, confidentiality and retention. Every field records whether it was extracted, recognized or edited, and by whom. Details save field by field as you type.
  • Durable processing. Lease-based jobs that survive restarts run in order: native PDF or plain-text extraction, SHA-256 exact-duplicate detection, and an optional recognition stage. Progress and retry are visible per document.
  • Entities, projects and processes. Link documents to people, companies, categories or projects. Collect them in projects, and follow processes as ordered threads with a due date.
  • Shares. Share links to a document or a project that are read-only and expire after seven days. Only a hash of the token is stored. Links can be listed and revoked, and share access is rate-limited.
  • Live updates. One TypedSocket connection per app pushes document changes, processing progress and library counts. Each push carries only what the recipient may see at that moment.
  • Streamed files. Uploads stream over TypedSocket and downloads and previews stream over plain HTTP, so no file is ever held whole in memory.
  • Audit trail. Security-relevant actions are recorded per organization, append-only, and shown as the Activity of documents, projects and entities.
  • Operations. Readiness and liveness endpoints, structured JSON logs without secrets or content, a container image, and a serve.zone deployment declaration.

Architecture

┌────────────────────────────────────────────────────────────┐
│ Browser: web app (ts_web/, dees-appui shell, prebuilt into  │
│ html/bundle.js)                                             │
├──────────────────────────────┬─────────────────────────────┤
│ /typedrequest (HTTP)         │ TypedSocket (uploads, live) │
│ /auth/* · /api/content/* · /health                         │
├────────────────────────────────────────────────────────────┤
│ Docbox server (ts/): request guard + tenant scope, feature  │
│ routers, identity, processing worker, live updates, audit   │
├──────────────────────────────┬─────────────────────────────┤
│ MongoDB-compatible database  │ S3-compatible bucket        │
│ (@lossless.org/client        │ (@lossless.org/client       │
│  /nosqldb)                   │  /objectstorage)            │
└──────────────────────────────┴─────────────────────────────┘
                idp.global (OIDC, organizations, roles)
docbox/
├── ts/                        # Server
│   ├── index.ts               # CLI (serve, org, migrate) and configuration
│   ├── classes.docbox.ts      # Server lifecycle
│   ├── persistence.ts         # Model binding and index preparation at startup
│   ├── classes.s3storage.ts   # Object storage
│   ├── mod_api/               # Request guard, validators, one TypedRouter per feature, content routes, live updates
│   ├── mod_identity/          # idp.global sign-in, sessions, socket binding, live membership checks
│   ├── mod_tenancy/           # Organizations, operator linking, the tenant scope every model reads through
│   ├── mod_audit/             # Audit trail
│   ├── mod_health/            # /health and /health/live
│   ├── mod_observability/     # JSON logger
│   ├── mod_processingmanager/ # Extraction, duplicate and recognition jobs
│   ├── mod_documentmanager/   # Documents and their files
│   ├── mod_entitymanager/  mod_projectmanager/  mod_processmanager/
│   ├── mod_scanmanager/       # Scan lineage
│   ├── mod_sharemanager/      # Hashed, expiring shares
│   ├── mod_usermanager/       # People who signed in, and labels of 1.x accounts
│   └── mod_eventhub/          # Domain events the managers raise
├── ts_migration/              # Versioned startup data migrations
├── ts_shared/                 # Data and request interfaces shared by server and web app
├── ts_web/                    # Web app (Web Components)
├── html/                      # index.html and the favicon; `pnpm build` writes the bundle and its third-party notices here
├── qenv.yml                   # The environment the server requires
├── cli.js                     # Production entry
├── cli.dev.js                 # Development entry with embedded database and storage
└── Dockerfile_##version##     # Container image

The server is Node.js and TypeScript on @api.global/typedserver. The API is TypedRequest, and sign-in uses @idp.global/sdk /relyingparty. PDF text comes from @push.rocks/smartpdf without a browser. The web app uses @design.estate/dees-element and @design.estate/dees-catalog. It is bundled at build time into html/, so the UI packages are build-time dependencies only.

Configuration

Docbox reads its configuration from the environment, or from .nogit/env.json / .nogit/env.yml in development. The database and object storage use the names that a serve.zone database and objectstorage binding injects. qenv.yml in the package declares the required names. docbox serve refuses to start while one is missing and names it, never its value. Invalid values also stop the start.

Variable Required Description Example
MONGODB_URI yes MongoDB connection URI whose path names the database. A URI without one is refused mongodb://user:pass@db:27017/docbox?authSource=docbox
S3_ENDPOINT_HOST yes Object storage host, without scheme or port s3.example.net
S3_PORT yes Object storage port 443
S3_USE_SSL yes true or false true
S3_BUCKET yes Bucket; created on first start when missing docbox
S3_ACCESS_KEY yes Object storage access key —
S3_SECRET_KEY yes Object storage secret key —
S3_REGION no Region, when the storage needs one eu-central-1
IDP_ISSUER yes The idp.global issuer https://idp.global
IDP_CLIENT_ID yes The OIDC client registered for this Docbox app-…
IDP_CLIENT_SECRET yes That client's secret —
PUBLIC_ORIGIN yes Docbox's public origin; the callback is <origin>/auth/callback https://docbox.example.com
DOCBOX_SESSION_SECRET yes 32 random bytes, base64: the session and CSRF key. Never reuse it elsewhere openssl rand -base64 32
DOCBOX_SEALING_KEY yes 32 random bytes, base64: seals secrets at rest (idp.global tokens) openssl rand -base64 32
DOCBOX_OPERATORS no idp.global subjects that operate this instance, separated by commas or spaces usr_123,usr_456
DOCBOX_AUTHORITY_CACHE_SECONDS no How long a confirmed membership is reused (0–600, default 60). Refusals are never cached 60
IDP_CA_CERT_FILE no PEM file of the CA that a private or local idp.global chains to. Trusted only for requests to the issuer and read once at start /run/secrets/idp-ca.pem
DOCBOX_PORT no Listening port (default 3050) 3050
DOCBOX_MAX_UPLOAD_BYTES no Largest upload in bytes (default 104857600, 100 MiB) 26214400
DOCBOX_CLIENT_IP_HEADER no Header a trusted reverse proxy appends the client address to. The share rate limit counts its last entry; when unset, it counts the transport peer x-forwarded-for
DOCBOX_TLS_CERT_PATH no PEM certificate chain for TLS served by Docbox itself, set together with the key /etc/ssl/docbox.crt
DOCBOX_TLS_KEY_PATH no PEM private key, set together with the certificate /etc/ssl/docbox.key

The session cookies are __Host- cookies, and TypedSocket refuses insecure transport off loopback, so a deployment's PUBLIC_ORIGIN is an https:// origin. Either terminate TLS in a reverse proxy or let Docbox serve it with DOCBOX_TLS_CERT_PATH and DOCBOX_TLS_KEY_PATH.

Sign-in, organizations and roles

  1. Register an OIDC client for Docbox at idp.global. It is a confidential client with the grant types authorization_code and refresh_token, the scopes openid profile email organizations roles, and exactly one redirect URI, <PUBLIC_ORIGIN>/auth/callback (idp.global accepts exact HTTPS redirect URIs only). A client is registered by an idp.global global administrator, or by an organization service principal through POST /machine/v1/oidc-clients for a domain its organization has proven by DNS TXT. See "Runtime OIDC Client Registration" in the idp.global readme. The client_id and secret become IDP_CLIENT_ID and IDP_CLIENT_SECRET.

  2. Name the operators in DOCBOX_OPERATORS. An operator may sign in without belonging to any organization, and manages organizations without ever reaching their documents.

  3. Create an organization and link it to its idp.global organization. A link is set once and never changed to a second organization. The operator can do this in the web app (Settings › Organizations, or the page shown to a session without an organization) or on the command line:

    node cli.js org create "Example GmbH" <idp.global organization id>
    node cli.js org list
    node cli.js org link <organization id> <idp.global organization id>
    

Members of a linked organization sign in with the role their idp.global membership grants:

idp.global role Docbox role Can
owner, admin admin Everything a member can, plus restricted documents, the member list and the audit trail
editor member Upload, file, edit, share and organize documents
viewer viewer Read the library

Any other role grants nothing, and members of unlinked organizations are refused. A session with several linked organizations switches between them in the app bar.

Run it yourself

Docbox needs three things next to it: a MongoDB-compatible database, S3-compatible object storage and an OIDC client at idp.global.

The image is built from this repository (Dockerfile_##version##, linux/amd64 and linux/arm64). It runs node cli.js serve as uid 10001, listens on DOCBOX_PORT (default 3050), writes nothing to its filesystem and carries a HEALTHCHECK against /health. The health check allows a start period of 600 s because data migrations run before the server listens. When Docbox serves TLS itself, the health probe (cli.healthcheck.js) speaks HTTPS to loopback and verifies the certificate for PUBLIC_ORIGIN's hostname.

  1. Register the OIDC client (see above).
  2. Generate the two keys, each 32 random bytes in base64 or base64url, never shared with another application: openssl rand -base64 32.
  3. Put TLS in front. Behind a proxy, set DOCBOX_CLIENT_IP_HEADER to the header that proxy appends the client address to.
  4. Start the stack, for example with Compose. MongoDB and MinIO are shown, and the ${…} values come from an .env file next to it:
services:
  docbox:
    build:
      context: .
      dockerfile: Dockerfile_##version##
    restart: unless-stopped
    ports:
      - '127.0.0.1:3050:3050' # your TLS proxy forwards to this
    environment:
      MONGODB_URI: mongodb://mongo:27017/docbox
      S3_ENDPOINT_HOST: minio
      S3_PORT: '9000'
      S3_USE_SSL: 'false'
      S3_BUCKET: docbox
      S3_ACCESS_KEY: docbox
      S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD}
      IDP_ISSUER: https://idp.global
      IDP_CLIENT_ID: ${IDP_CLIENT_ID}
      IDP_CLIENT_SECRET: ${IDP_CLIENT_SECRET}
      PUBLIC_ORIGIN: https://docbox.example.com
      DOCBOX_SESSION_SECRET: ${DOCBOX_SESSION_SECRET}
      DOCBOX_SEALING_KEY: ${DOCBOX_SEALING_KEY}
      DOCBOX_OPERATORS: ${DOCBOX_OPERATORS}
      DOCBOX_CLIENT_IP_HEADER: x-forwarded-for # only behind a proxy that appends it
    depends_on:
      - mongo
      - minio
  mongo:
    image: mongo:8
    restart: unless-stopped
    volumes:
      - mongo-data:/data/db
  minio:
    image: quay.io/minio/minio
    command: server /data
    restart: unless-stopped
    environment:
      MINIO_ROOT_USER: docbox
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    volumes:
      - minio-data:/data
volumes:
  mongo-data:
  minio-data:
  1. Once /health answers 200, link an organization: docker compose exec docbox node cli.js org create "Example GmbH" <idp.global organization id>.

Back up the database and the bucket together, because they form one dataset.

Deploy on serve.zone

.smartconfig.json carries Docbox's @git.zone/tsdeploy declaration: the public domain and its route (readiness /health, expecting 200), container port 3050, no volumes, the database and objectstorage capabilities, the complete environment surface including every platform-injected name, and built-in release evidence. The platform supplies MONGODB_URI and the S3_* names through the capability bindings.

Follow Developers → Integrate a new app in the serve.zone documentation step by step. It is the canonical recipe; the steps below cover only what is specific to Docbox:

  1. Deployment machine user and grant: an organization-service-slot grant for the chosen service id, then tsdeploy link --serviceId '<service id>'.

  2. Service-owned secrets:

    • PUBLIC_ORIGIN: the https:// origin of the declared domain.
    • IDP_ISSUER.
    • DOCBOX_SESSION_SECRET and DOCBOX_SEALING_KEY: each created as a generated value, 32 bytes, base64url.
    • DOCBOX_OPERATORS.

    Never create the database or object storage names; the platform publishes them.

  3. OIDC client: registered through the typed admin operation (fresh passkey) or a registration service principal, with the redirect URI https://<domain>/auth/callback. Store IDP_CLIENT_ID and IDP_CLIENT_SECRET as two more service-owned secrets.

  4. Deploy: run tsdeploy deploy --dryRun first, then tsdeploy deploy --mode greenfield as the recipe states.

  5. Runtime spec: once the reserve has created the service, pin it to one node (setServiceRuntimeSpec). The bindings and the route need exactly one pinned node.

  6. Route and DNS: the deploy promotes them for the declared domain; never edit DNS ahead of it.

  7. Access verification: from both a public and a trusted-network vantage point, https://<domain>/health answers 200 without a redirect, and a sign-in completes.

Recovery (retry, cleanup, restore) is described under Operations → Production rollouts and recovery in the same documentation.

Upgrading from 1.6.1

Back up the database and the bucket first. There is no way back to 1.6.1.

2.0 is a breaking release:

  • Sign-in moves to idp.global. Local accounts, passwords, Docbox JWTs and DOCBOX_BOOTSTRAP_ADMIN_PASSWORD are gone.

  • The data moves into organizations.

  • The configuration uses the serve.zone names:

    • MONGODB_URL + MONGODB_NAME become MONGODB_URI, with the database in the path.
    • S3_ENDPOINT becomes S3_ENDPOINT_HOST.
    • S3_ACCESSKEY becomes S3_ACCESS_KEY, and S3_SECRETKEY becomes S3_SECRET_KEY.
    • S3_USESSL becomes S3_USE_SSL, which is now required.

    The old names are not read.

  • Request contracts lose their token field, and list pages are bounded to 1000 items. See changelog.md for every contract change.

To upgrade:

  1. Stop 1.6.1, then back up the database and the bucket.

  2. Set the 2.0 environment from the configuration table, including the idp.global client and the two keys.

  3. Check what the migrations would change. The dry run only reads, and prints one report per step:

    node cli.js migrate --dry-run
    
  4. Start 2.0, or run node cli.js migrate first. The versioned migrations run before the server listens:

    • The document model and scan lineage are updated.
    • The 1.x JWT signing key is removed.
    • All existing data moves into one organization, org_initial, which is not linked yet.
    • The 1.x accounts become read-only name labels, and their password hashes are deleted.
    • Every stored object is copied under orgs/<organization>/, verified by size and SHA-256, switched, and only then deleted.

    Every step is recorded once done. A stopped run resumes where it left off, and several instances may start at once.

  5. Link the migrated organization: node cli.js org link org_initial <idp.global organization id>.

Command line

Command Description
node cli.js / node cli.js serve Run the server (checks qenv.yml's required names first)
node cli.js org list Every organization and its link, as JSON
node cli.js org create <name> [<idp.global organization id>] Create an organization, optionally linked right away
node cli.js org link <organization id> <idp.global organization id> Link an unlinked organization
node cli.js migrate [--dry-run] Bring the database and bucket to the current version without starting the server

The org and migrate commands need only the database and object storage variables. org create and org link are recorded in the audit trail with the command line (cli) as the actor.

Health endpoints

Both endpoints are unauthenticated and reveal nothing about the deployment:

  • GET /health (readiness) answers 200 once three checks pass: the database answers a ping, the bucket answers a probe, and the startup migrations are done. Otherwise it answers 503 with { "healthy": …, "checks": [{ "name": "database" | "objectStorage" | "migrations", "healthy": …, "errorMessage"?: <reason word> }] }. Each probe is bounded to 2 s and its answer is reused for 2 s. idp.global is deliberately not part of readiness.
  • GET /health/live (liveness) answers 200 whenever the process serves HTTP.

API overview

The web app and any other client use TypedRequest at /typedrequest (HTTP) or over TypedSocket. The request and response interfaces live in ts_shared/. No request carries a credential:

  • HTTP requests are authorized by the session cookie, sent from the public origin.
  • A TypedSocket connection registers its session once with registerSocketSession.

Lists are paged, with at most 1000 items per page.

HTTP routes

Route Description Auth
GET /auth/login?return=/path Start the idp.global sign-in —
GET /auth/callback The OIDC redirect target —
GET /auth/session The session and its CSRF token, or null —
POST /auth/logout End the session ({ csrfToken }); its socket and live updates end too Session
GET /api/content/documents/<id> Stream a document's file; restricted documents for admins only Session cookie
GET /api/content/shared/<id> Stream a file of a share (token in the x-docbox-share-token header, never in the URL) Share token

With ?disposition=inline, PDFs, PNG, JPEG, GIF, WebP and plain text show in the browser. Everything else, and every request without the parameter, is served as a download with the UTF-8 file name. Responses carry Content-Length, X-Content-Type-Options: nosniff and Cache-Control: private, no-store. Byte ranges are not served yet (Accept-Ranges: none). The status codes are:

  • 401 without a session or token.
  • 403 for a document the role may not read.
  • 404 for a document that does not exist in the caller's organization or share.
  • 429 when the share rate limit is spent.

Typed requests

Area Methods
Session getSession, selectOrganization, registerSocketSession
Operator listOrganizations, createOrganization, linkOrganization (operators only)
Users getUsers (admins), getUserLabels
Documents uploadDocument (streamed over TypedSocket), getDocuments, getDocumentById, renameDocument, updateDocument, updateDocumentFields, setDocumentFlag, reviewDocument, archiveDocument, unarchiveDocument, deleteDocument, getDocumentsByEntity, createDocumentShare, getDocumentBuffer
Processing getDocumentProcessingJobs, retryDocumentProcessingJob
Library getLibrarySummary, getLibraryFacets, getCapabilities, getOverviewStats, getEntityDocumentCounts
Entities createEntity, getEntities, getEntityById, updateEntity, deleteEntity
Projects createProject, getProjects, getProjectById, updateProject, addDocumentsToProject, removeDocumentsFromProject, deleteProject, createProjectShare
Processes createProcess, getProcesses, updateProcess, getProcessThread, deleteProcess
Shares listShares, revokeShare, resolveShare and getSharedDocumentBuffer (share token)
Audit getAuditEvents (admins)
Live updates subscribeLiveUpdates, unsubscribeLiveUpdates

getDocumentBuffer and getSharedDocumentBuffer return a file base64-encoded; prefer the streamed content routes. resolveShare, getSharedDocumentBuffer and the shared-file route share one budget per client of 120 requests a minute.

Lists that hold documents only ever show a caller the documents it may see. A caller who replaces such a list keeps the documents it cannot see. A project or process holds at most 10 000 documents, and concurrent changes to one never overwrite each other.

Live updates

After subscribeLiveUpdates, the server pushes three messages over the socket:

  • pushDocumentChanged: a document was created, updated, reviewed, flagged, unflagged, archived, unarchived or deleted, or became hidden to the recipient.
  • pushProcessingProgress: a document's complete job list.
  • pushLibrarySummaryChanged: the recipient's scope counts.

Each push carries only what that recipient may see at the time. Clients cannot tag their connection themselves.

Audit trail and logs

The audit trail records these actions per organization:

  • Sessions: session.login, session.logout, session.select.
  • Organizations: organization.create, organization.link.
  • Shares: share.create, share.revoke.
  • Documents: document.delete, document.archive, document.unarchive, document.confidentiality.
  • Other deletions: project.delete, process.delete, entity.delete.

Each entry names who acted (a user, the operator or the command line) and when. Entries are never changed or removed, and never carry document content.

The server writes one JSON object per line. Each API request and file download is logged with its request id, method or route, organization, subject, duration and outcome, alongside startup and failure events. Payloads, file contents, tokens and configuration values are never logged, and fields named like credentials are redacted.

Recognition

The recognition stage is pluggable and off by default. Programmatic users of Docbox pass recognition: { recognizer } in IDocboxConfig. Restricted documents are withheld from a recognizer unless recognizeRestricted is set. Recognition never overwrites an edited or extracted value, and it proposes entities for review without applying them.

Web app

The web app is a dees-appui shell. Every screen has a hash route, and filters, search and the selected document live in the hash query, so Reload, Back and Forward keep your place.

View Route Description
Library #library/:scope? Inbox, Flagged, Recent, All and Archive, with filters, search and an inspector for filing, details and processing
Document #doc/:id/:tab? Preview beside filing and details, extracted text, pages and Activity
Capture #capture Upload several files with per-file progress and processing stages. A camera field comes first on phones
Entities #entities/:id? Entities by kind, with one entity's documents, processes, details and Activity
Projects #projects/:id? Active and archived projects with their documents, processes, details, share links and Activity
Processes #processes/:id? Open, waiting and closed processes as threads
Settings #settings/:section? Members (admins), Connections, Capabilities, Appearance, Organizations (operators)
Share #share/:token Public, read-only page of a shared document or project

Development

The project uses pnpm and the @git.zone toolchain.

pnpm install
pnpm build        # compile ts/, ts_shared/, ts_migration/ and bundle ts_web/ into html/
pnpm test         # the full test suite; needs no external services
pnpm startDev     # run with an embedded database and object storage
pnpm run watch    # local idp.global + server from source, restarted on changes, and the web bundle
pnpm start        # run the built server (node cli.js)

pnpm startDev needs no MongoDB, no S3 and no Docker. It starts @lossless.org/nosqldb and @lossless.org/objectstorage in-process and points Docbox at them. Sign-in is idp.global in development too, so the IDP_*, PUBLIC_ORIGIN, DOCBOX_SESSION_SECRET and DOCBOX_SEALING_KEY values above are required, and DOCBOX_OPERATORS is usually set as well. A local idp.global under its own CA needs IDP_CA_CERT_FILE. State persists under .nogit/devstack; delete that folder to start over. DOCBOX_PORT sets the port, and DOCBOX_DEV_S3_PORT and DOCBOX_DEV_DB_NAME override the embedded storage defaults.

pnpm run watch

pnpm run watch runs Docbox from source, restarts it on changes under ts/, ts_migration/ and the launcher's ts_dev/devserve.*.ts, and rebuilds the web bundle. Sign-in is always idp.global: by default a local idp.global that the watch starts itself, or the public one when you configure it.

  • Storage comes from gitzone services, which starts the database and object storage and writes their connection names (MONGODB_URI, S3_*) to .nogit/env.json. Docbox reads them from there; start the services before the watch.
  • The local idp.global (pnpm run devIdp, cli.devidp.js) runs @idp.global/devidp: the idp.global app image in Docker, a kernel-keyring namespace docbox-dev that keeps its CA, client and personas stable across restarts, and TLS from its own development CA. It serves https://idp.localhost:8443 with login., app. and superadmin.idp.localhost beside it (DOCBOX_DEV_IDP_PORT changes the port) and registers Docbox as https://localhost:3050 (DOCBOX_PORT), or at PUBLIC_ORIGIN when that is set, which must then be an https origin with a host name, such as https://docbox.localhost:3050; Docbox's TLS certificate is issued for that host name. It needs Docker and a usable Linux kernel keyring. Ctrl+C gives it up to 30 seconds (stopGracePeriod) to remove its containers and networks.
  • The launcher (pnpm run startTsDev, cli.devserve.js) waits up to six minutes for the local idp.global and fills in only what is unset: IDP_ISSUER, IDP_CLIENT_ID, IDP_CLIENT_SECRET, IDP_CA_CERT_FILE, PUBLIC_ORIGIN, DOCBOX_TLS_CERT_PATH and DOCBOX_TLS_KEY_PATH (Docbox serves HTTPS with a leaf from the same CA), DOCBOX_OPERATORS (the testsuperadmin persona) and a stable development DOCBOX_SESSION_SECRET and DOCBOX_SEALING_KEY, generated once into .nogit/docbox-dev-secrets.json. Then it runs docbox serve.

The local idp.global writes its handoff to .nogit/devidp/ (mode 0600) and removes it when it stops; the launcher refuses a handoff whose idp.global is gone, and a PUBLIC_ORIGIN other than the one the running local idp.global registered (restart the watch after changing it). The log names the issuer, the persona e-mail addresses and the CA file; the passwords and subjects of testuser, testmoderator and testsuperadmin are in .nogit/devidp/runtime.json.

To sign in, trust .nogit/devidp/ca.pem as a certificate authority in the browser (a separate browser profile keeps it out of your everyday one), open https://localhost:3050 and sign in as a persona. Chromium and Firefox resolve *.localhost to the loopback address themselves. On a remote development host, forward both ports: ssh -L 3050:localhost:3050 -L 8443:localhost:8443 <host>.

Setting IDP_ISSUER (with IDP_CLIENT_ID, IDP_CLIENT_SECRET and the rest of the sign-in names, in the environment or .nogit/env.json) uses that idp.global instead, for example the public idp.global: the launcher then neither waits for the local one nor fills in anything. IDP_CLIENT_ID, IDP_CLIENT_SECRET or IDP_CA_CERT_FILE without IDP_ISSUER is refused, so a configuration is never mixed with the local idp.global.

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license.md file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH
Registered at District Court Bremen HRB 35230 HB, Germany

For any legal inquiries or further information, please contact us via email at hello@task.vc.

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

S
Description
a standardized way to store documents
Readme
23 MiB
Languages
TypeScript 99.5%
JavaScript 0.5%