Skip to content

Architecture

How a request moves through CORE.

One path for every interface: identity, permission, capability, event. The CoreClient contract, the authorization formula and where the implementation stands today.

Interfaces

One CORE, many interfaces.

Website, internal app, mobile app, chat, agent, API. Apps become views into CORE.

2finity CORE and the interfaces and participants connected to it

Interface

Website

Public sites and portals that read content and catalog data and submit forms through CORE.

Uses

  • Identity (used)
  • Organizations
  • People
  • Relationships
  • Knowledge (used)
  • Workflows
  • Commerce (used)
  • Finance
  • Communication
  • Data (used)

Example capabilities

  • page.get
  • catalog.list
  • form.submit

Website selected. Uses 4 of 10 layers.

CORE
The shared operating layer. Ten layers: Identity, Organizations, People, Relationships, Knowledge, Workflows, Commerce, Finance, Communication, Data.
Website (interface)
Public sites and portals that read content and catalog data and submit forms through CORE. Uses the Identity, Knowledge, Commerce and Data layers. Example capabilities: page.get, catalog.list, form.submit.
Applications (interface)
Internal, mobile and dashboard apps: views into CORE with the signed-in identity's permissions. Uses the Identity, Organizations, People, Workflows and Data layers. Example capabilities: customer.get, workflow.start, approval.decide.
Chat (interface)
2finity.chat and other conversational interfaces: language resolved to capabilities, with approval. Uses the Identity, Knowledge, Workflows, Finance and Communication layers. Example capabilities: site.content.update, invoice.create, permission.grant.
Agents (interface)
Actors with their own identity, an owner and scoped permissions; every action leaves an audit event. Uses the Identity, Knowledge, Workflows and Communication layers. Example capabilities: site.publish, deployment.rollback, workflow.start.
People (participant)
Humans in any context: professional, employee, customer or supplier, with one identity throughout. Uses the Identity, People, Relationships and Communication layers. Example capabilities: customer.get, permission.grant, message.send.
Companies (participant)
Organizations that own their data, run their workflows and decide who and what may act inside them. Uses the Organizations, People, Relationships, Commerce and Finance layers. Example capabilities: organization.get, invoice.create, order.update.
Partners (participant)
Other organizations connected by a relationship: suppliers, resellers and agencies see what it grants. Uses the Identity, Relationships, Commerce and Data layers. Example capabilities: catalog.product.get, order.update, permission.grant.
Enterprise (participant)
Large organizations running CORE in an isolated deployment with their own identity provider and policies. Uses the Identity, Organizations, Workflows, Finance and Data layers. Example capabilities: permission.grant, deployment.publish, workflow.start.
Interfaces
  • Website
  • Portal
  • Internal app
  • Mobile app
  • 2finity.chat
  • Agent
  • API
  • Partner app
  • Enterprise integration

Request flow

Seven stages, one path

An interface calls the CoreClient. The client resolves the acting identity, asks whether that identity may invoke the capability on the resource, runs the capability against the layer entities and emits an event. The result returns to the interface; the event stays in CORE.

The stages are the same for a form submission, an API call, an agent’s action and a chat message. What differs is the origin, and the origin is recorded on the event.

  1. Interface (A website, application, agent, API client or chat client makes the request.)
  2. CoreClient (The typed contract every interface uses to reach CORE.)
  3. Identity (Who or what is asking, resolved from the session or token.)
  4. Permission (May this identity invoke this capability on this resource?)
  5. Capability (The named action: validated input, handler, transaction.)
  6. Layer entities (The records the capability reads and changes, each in its layer.)
  7. Event (What happened, by whom, on what, recorded for audit.)
Illustration

Contract

The CoreClient surface

Five namespaces cover everything an interface can do. identity.current() answers who is asking, entities.get() and entities.list() read typed records, capabilities.invoke() is the only way to change anything, permissions.can() answers the authorization formula, and events.emit() records what happened.

The surface is small on purpose. A website generated by the System Migrator, an internal app and an agent runtime all compile against the same five namespaces, so swapping the implementation behind them does not touch the interfaces.

CoreClient · TypeScript
const core = getCore();

const actor = await core.identity.current();                 // who is asking
const page = await core.entities.get<Page>('page', 'home');  // what they are looking at
const history = await core.entities.list<Revision>('revision', { where: { page: 'home' }, limit: 5 });

const resource = { type: 'page', id: 'home' };
if (await core.permissions.can(actor, 'site.content.update', resource)) {
  // Validates the input, runs the handler in a transaction, emits site.content.updated.
  await core.capabilities.invoke('site.content.update', {
    page: 'home',
    block: 'hero',
    headline: 'Build interfaces, not backends.',
  });
}

await core.events.emit('page.viewed', { page: page?.id, revisions: history.length, by: actor?.id ?? 'public' });
The contract that 2finity.com, agents, Migrator-generated apps and, later, 2finity.chat share. On the public pages of 2finity.com the client is local and read-only; behind the administrator sign-in the same contract runs against a database.
The five CoreClient namespaces and what each answers
MethodMeaning
identity.current()Who is asking: the acting identity from the session or token, or the public actor.
entities.get() / entities.list()Typed reads of layer entities, filtered by what the actor may see.
capabilities.invoke()The only way to change anything: identity, permission, handler, event, in that order.
permissions.can()The authorization formula, answered for an actor, a capability and a resource.
events.emit()What happened, recorded for audit and for every other interface to react to.

Before CORE, each interface (Website, Internal app and Mobile app) rebuilds the same backend: Authentication, Users, Permissions, Organizations, Database models, Workflows, Commerce, Integrations, Communication and Audit history. With CORE, the same interfaces are views into one CORE whose layers (Identity, Organizations, People, Relationships, Knowledge, Workflows, Commerce, Finance, Communication and Data) are built once behind one capability contract.

One contract instead of one backend per interface.

Authorization

The authorization formula

Identity + Organization + Relationship + Role + Resource + Capability, answered as allow or deny. Every term is a record in CORE: the identity that is asking, the organization whose boundary applies, the relationship that connects them, the role that relationship carries, the resource in question and the capability being invoked.

Because the terms are records, authorization is explainable. When a request is denied, CORE can say which term failed; when it is allowed, the event records every term that made it so.

Authorization is decided from Identity (who is asking), Organization (inside which boundary), Relationship (how are they connected), Role (in what capacity), Resource (on what) and Capability (doing what). The answer is allow or deny.

Illustration

Model

Entities live in layers

Every entity type belongs to exactly one layer: a Session to Identity, a Team to Organizations, a Lead to People, a Mandate to Relationships, a Revision to Knowledge, an Approval to Workflows, an Order to Commerce, an Invoice to Finance, a Thread to Communication and an Audit entry to Data.

Layers are not silos. A capability in one layer reads from others: invoice.create reads the order in Commerce and the customer in People before it writes to Finance. The layer tells you where a record lives and which question it answers.

Example entity types and the layer each belongs to
Entity typesLayer
  • Identity
  • Credential
  • Session
01Identity
  • Organization
  • Team
  • Department
02Organizations
  • Person
  • Customer
  • Employee
03People
  • Relationship
  • Relationship type
  • Role
04Relationships
  • Document
  • Page
  • Policy
05Knowledge
  • Workflow
  • Task
  • Approval
06Workflows
  • Product
  • Service
  • Catalog
07Commerce
  • Invoice
  • Invoice line
  • Payment
08Finance
  • Conversation
  • Message
  • Thread
09Communication
  • Entity type
  • Record
  • Field
10Data

Audit

Events are the audit log

Every capability invocation emits an event with the actor, the capability, the resource and the outcome. Events are entities in the Data layer, so they can be queried with event.query and listed with audit.list under the same permission checks as everything else.

Nothing is deleted. A rollback is a new revision, an ended relationship keeps its validity period, and a revoked permission leaves the grant and the revocation side by side.

Example events, oldest first: time, event name, actor and reference.

  1. 12:04:11site.content.updated#184
  2. 12:04:12approval.decided#184
  3. 12:04:13site.published#184
  4. 12:09:40invoice.createdINV-2041
  5. 12:11:02permission.grantededitor
  6. 12:15:27workflow.startedonboarding
Example events. Times are illustrative.

Status

Local today, remote later

createCore() chooses the implementation from the environment. On the public pages of 2finity.com the client is local and read-only: it serves the content of this site as entities. Behind the administrator sign-in the same contract runs against a database, and creating a CORE is its first capability.

A remote mode is reserved for a hosted CORE reached over HTTP with a bearer token. It is a placeholder today; the client package, @2finity/core-client, is planned.

Remote contract · HTTPPlanned
  • GET /identity/current
  • GET /entities/{type}/{id}
  • POST /entities/{type}
  • POST /capabilities/{name}
  • POST /events
  • POST /permissions/can

Bearer token in the Authorization header. Not implemented on 2finity.com; the local client serves every public page.

Identity

Identity provider

Identity resolution sits behind one interface so the provider can change without touching capabilities. Today the provider is the administrator session of 2finity.com. 2finity Identity, the planned OpenID Connect provider at 2finity.com, is the next implementation of the same interface.

Enterprise deployments plug in their own OpenID Connect provider at the same point.

Next

Every capability, and the identity behind each request.