Onboarding

Getting started with SCPN Studio

Five steps from reading the platform to verifying your first sealed evidence bundle. Each step expands to show the goal, the links you need, and the next action.

1 What is SCPN Studio?

SCPN Studio is a federation of standalone scientific studios. Each studio owns its domain, its verbs, and its evidence, while the Hub federates their interfaces and audits every claim against the shared studio.*.v1 contract.

Read the platform overview →
2 Explore a project

Browse the live federation to see how a studio advertises its capabilities, its evidence types, and its latest sealed results. Every project page is reflected from its source repository.

Browse projects →
3 Run a demo studio

Open the hosted demo studio to see a federated UI load inside the Hub shell, emit a studio.demo.v1 evidence bundle, and verify it in the browser without installing anything.

Launch demo studio →
4 Verify your first evidence bundle

Download a sealed artifact, inspect its studio.publication-seal.v1 envelope, and check the content digest and signature against the pinned root key and well-known keyring.

Open the trust guide →
5 Create an account / subscribe

Create a free account to run jobs in your own tenant, or subscribe to the research newsletter to receive releases, preprints, and transparency-log checkpoints.

Create account →
Runnable quickstart

SCPN Studio quickstart notebook

This notebook demonstrates the end-to-end SCPN Studio flow:

1. Create an account through the commerce API.

2. Run a deterministic hosted-studio demo.

3. Download and verify a sample evidence bundle with the platform SDK.

**Prerequisites**

- Python 3.12+

- `httpx` installed (`pip install httpx`)

- `scpn-studio-platform` installed (`pip install -e /path/to/SCPN-STUDIO-PLATFORM`)

- A running commerce backend (or use `https://www.anulum.org` for the public API).

Download the notebook → Interactive API docs

  1. 1. Create an account

    Registration is asynchronous: the endpoint queues a verification email and returns `202 Accepted`. Duplicate emails are accepted silently so the endpoint does not leak account existence.

    
                      import uuid
    
    email = f"user-{uuid.uuid4().hex[:8]}@example.org"
    password = "correct-horse-battery-staple!42"
    display_name = "Notebook User"
    
    resp = client.post('/api/v1/auth/register', json={
        'email': email,
        'display_name': display_name,
        'password': password,
    })
    print(resp.status_code, resp.text)
                    
  2. 2. Verify email and log in (local development)

    In production the verification link is sent by email. For a local backend running the recording mail transport, inspect the mail outbox or call the verification endpoint directly if you have the token. Once verified, log in to obtain the session cookies.

    Skip this cell when running against the public site unless you own the mailbox.

    
                      # This cell is a placeholder for local verification.
    # In a real local run you would read the verification token from the mail drain
    # or backend logs and POST it to /api/v1/auth/verify-email.
    
    login = client.post('/api/v1/auth/login', json={
        'email': email,
        'password': password,
    })
    print(login.status_code, login.text)
                    
  3. 3. Read the current account

    The `/api/v1/auth/me` endpoint returns the authenticated account, including its federation-wide tier.

    
                      me = client.get('/api/v1/auth/me')
    print(me.status_code, json.dumps(me.json(), indent=2))
                    
  4. 4. Probe API health

    The public status and health endpoints need no authentication.

    
                      for path in ['/healthz', '/health/ready']:
        r = client.get(path)
        print(path, r.status_code, r.json())
                    
  5. 5. Download and inspect the OpenAPI spec

    The commerce API publishes its OpenAPI schema at `/api/v1/openapi.json`. This is the same schema rendered by Scalar at `/docs/api/`.

    
                      spec = client.get('/api/v1/openapi.json')
    print(spec.status_code, spec.headers.get('content-type'))
    openapi = spec.json()
    print('title:', openapi['info']['title'])
    print('version:', openapi['info']['version'])
    print('paths:', list(openapi['paths'])[:10])
                    
  6. 6. Verify a sample evidence bundle

    The portal hosts sample RO-Crate evidence bundles. We download one and use the platform SDK to validate its claim boundary and digest.

    
                      import zipfile
    import tempfile
    from pathlib import Path
    
    bundle_url = 'https://www.anulum.org/evidence/scpn-control.rocrate.zip'
    bundle_bytes = httpx.get(bundle_url, follow_redirects=True, timeout=30).content
    print('Downloaded', len(bundle_bytes), 'bytes')
    
    with tempfile.TemporaryDirectory() as tmp:
        archive = Path(tmp) / 'bundle.zip'
        archive.write_bytes(bundle_bytes)
        with zipfile.ZipFile(archive) as zf:
            zf.extractall(tmp)
            print('Entries:', zf.namelist()[:20])
        metadata_path = Path(tmp) / 'ro-crate-metadata.json'
        if metadata_path.exists():
            metadata = json.loads(metadata_path.read_text())
            print('RO-Crate @id:', metadata.get('@id'))
            print('Entities:', len(metadata.get('@graph', [])))
                    
    
                      # If scpn-studio-platform is installed, verify the bundle digest.
    try:
        from scpn_studio_platform.digest import file_digest
        digest = file_digest(archive)
        print('Bundle SHA-256 digest:', digest)
    except ImportError as exc:
        print('scpn-studio-platform not installed:', exc)
                    
  7. Next steps

    • Read the interactive API docs at `https://www.anulum.org/docs/api/`.
    • Explore the platform SDK source in `SCPN-STUDIO-PLATFORM/src/scpn_studio_platform/`.
    • Run the local smoke test: `pnpm --filter scpn-studio-portal run smoke:local`.