API Architecture Overview¶
Core Concept
Full Calendar Remastered exposes a unified, scope-gated API layer that powers both in-vault JavaScript integrations (third-party plugins, DataviewJS, Templater) and external REST client scripts (cURL, Python, CLI tools). All requests funnel through capability checks into InternalAPI and EventCache.
High-Level System Architecture¶
The API architecture employs a strict Bouncer Design Pattern. Third-party callers never hold direct references to plugin singletons or internal memory stores. Instead, they receive a scoped AuthorizedAPI instance generated by PublicAPI.withToken().
flowchart TD
subgraph Clients["Integration Clients"]
TP["Third-Party Obsidian Plugin"]
DV["DataviewJS / Templater Script"]
EXT["External CLI / Python / cURL"]
end
subgraph Security["Security & Access Gate"]
PAPI["PublicAPI (app.plugins.plugins['full-calendar'].api)"]
LSRV["LocalServer Daemon (127.0.0.1:8540)"]
AMOD["AuthorizationModal (Consent Prompt)"]
TSTORE["Settings Storage (apiTokens)"]
end
subgraph AuthLayer["Scoped Capability API"]
AAPI["AuthorizedAPI Instance"]
SCHK["assertScope(grantedScopes, required)"]
end
subgraph InternalCore["Core Plugin State Authority"]
IAPI["InternalAPI Dispatcher"]
ECACHE["EventCache (Canonical State)"]
PREG["ProviderRegistry (Remote & File I/O)"]
PSTATE["PluginState Singletons"]
end
TP -->|"requestAccess()"| PAPI
PAPI -->|"Prompt User"| AMOD
AMOD -->|"Grant Token"| TSTORE
TP -->|"withToken(token)"| PAPI
DV -->|"withToken(PAT)"| PAPI
PAPI -->|"Validate Token"| TSTORE
PAPI -->|"Instantiate"| AAPI
EXT -->|"HTTP + Bearer Token"| LSRV
LSRV -->|"withToken(token)"| PAPI
AAPI -->|"Method Call"| SCHK
SCHK -->|"Pass"| IAPI
IAPI --> ECACHE
IAPI --> PREG
IAPI --> PSTATE
Component Ownership Matrix¶
| Layer | Responsibility | Must Own | Must NOT Own |
|---|---|---|---|
PublicAPI |
Entry point attached to app.plugins.plugins['full-calendar'].api. Manages access token lookup, modal prompts, and legacy token migration. |
Token validation, modal dispatching, PAT resolution. | Direct event data, file operations, HTTP server logic. |
LocalServer |
Embedded Node.js HTTP listener (127.0.0.1:${port}). Parses HTTP requests, CORS headers, and Bearer tokens. |
Port binding, HTTP routing, JSON body parsing. | Business logic, cache filtering engines, UI state. |
AuthorizedAPI |
Ephemeral closure wrapper implementing authorized API calls. Enforces assertScope() per method call. |
Scope verification, forwarding calls to InternalAPI or EventCache. |
Persistent token storage, raw internal singletons. |
InternalAPI |
Execution engine bridging API requests to workspace leaves and cache engine. | Active view tracking, calendar tab opening, view changing. | Client permission checking, HTTP response formatting. |
EventCache |
Single source of truth for cached events and event index operations. | In-memory event index, mutation dispatching, file sync. | API token validation, UI view state management. |
Request Execution Lifecycle¶
sequenceDiagram
autonumber
participant Client as External REST Client / JS Script
participant Bouncer as LocalServer / PublicAPI
participant Authorized as AuthorizedAPI Closure
participant Internal as InternalAPI Engine
participant Cache as EventCache
Client->>Bouncer: Call Endpoint / Method with Token
Bouncer->>Bouncer: Lookup Token in Settings (apiTokens)
alt Token Missing or Invalid
Bouncer-->>Client: Return 401 Unauthorized / null
else Token Valid
Bouncer->>Bouncer: Update lastUsedAt timestamp (async save)
Bouncer->>Authorized: Return / Instantiate AuthorizedAPI
Authorized->>Authorized: assertScope(grantedScopes, requiredScope)
alt Scope Missing
Authorized-->>Client: Throw Error / Return 403 Forbidden
else Scope Granted
Authorized->>Internal: Forward Operation (e.g. getEvents)
Internal->>Cache: Query Event Store / Filter Engine
Cache-->>Internal: Return Matching Queryables
Internal-->>Authorized: Return Normalized Event Objects
Authorized-->>Client: Return JSON Result / Typed Objects
end
end
Security Model & Sandbox Guarantees¶
- Process Boundary Isolation: Third-party plugins cannot access internal data structures (
EventCache,ProviderRegistry) directly without possessing a token withsystem:full-accessscope. - Localhost Restriction: The REST server (
LocalServer) forces network interface binding to127.0.0.1. Requests originating outside local loopback are rejected by the operating system kernel network stack. - Mobile Platform Exclusions: Obsidian runs on desktop (Electron/Node.js) and mobile (Capacitor/WebView). The
LocalServerdetects mobile platforms viaPluginState.isMobile()and disables the HTTP listener, avoiding mobile runtime crashes while keeping the JSPublicAPIavailable. - Token Persistence: Personal Access Tokens (PATs) and plugin authorization records are persisted securely in Obsidian's plugin configuration (
data.jsonunderapiTokens).
Reading Order & Detailed References¶
- Public JS API: JS entry points,
requestAccess(), and completeAuthorizedAPImethod contracts. - REST Server Specification: HTTP REST routes, schemas, headers, status codes, and cURL examples.
- Scopes & Authorization: Detailed breakdown of permissions, risks, and token storage format.
- Internal API Engine: View tracking, workspace leaf resolution, and cache querying mechanics.
- Recipes & Blueprints: Complete recipes for plugins, DataviewJS, Templater, Python, and shell scripts.
Back to API Index · Public JS API · REST Server · Scopes & Permissions