Aurum 2.0 & Aurora — technical report
Architecture of a modular platform, isolated plugins, and a visual editor
Overview
A technical account of the Aurum 2.0 architecture, plugin runtime, Aurora Editor, security boundaries, and delivery model.
Technologies Used
Platform objective
Aurum 2.0 separates bespoke customer experience from repeatable operational work. Websites remain independent Vue and Nuxt applications while content, permissions, domain data, publishing, and delivery use shared contracts.
The platform is not tied to one industry. Business capabilities ship as versioned plugins, allowing new domains to evolve without expanding the core.
A small core and product plugins
The Aurum core owns the concerns that require shared trust:
- identity, sessions, and roles;
- the plugin catalog and versions;
- audit and observability;
- contract validation;
- controlled activation.
A plugin contributes a complete product capability: backend endpoints, administration UI, configuration, permissions, and private data storage. Aurora Editor, Contact Messages, and domain-specific modules are peers in the same runtime.
Isolation and AI-assisted code
Code generated or modified with AI receives no additional trust. Every plugin crosses the same explicit contract boundary:
- Its manifest declares SDK compatibility, configuration, endpoints, and permissions.
- Access is granted per capability according to least privilege.
- Data and migrations remain private to the plugin.
- A candidate is verified before activation and active traffic.
The model does not assume generated code is flawless. It contains the possible consequences of a mistake and prevents accidental coupling between modules.
Aurora Editor
Aurora turns the final website into the editing surface. Developers mark editable elements with stable keys, fallback values, and editorial context. Layout, responsiveness, and rendering remain owned by the client application.
The embedded website receives no administration token and performs no direct persistence. It sends editing intent to the trusted parent through a versioned message protocol with origin control, nonce-based handshakes, schema validation, correlation identifiers, and revisioned state updates.
Drafts, publishing, and history
Aurora owns drafts, autosave, revisions, conflicts, and published state. Writes contain an expected revision and idempotency key, so concurrent work cannot be silently overwritten.
Publishing creates an immutable release for a specific revision. A rollback becomes a new release based on an earlier snapshot, preserving a linear and auditable history.
Safe activation
A new plugin version is prepared away from active traffic. Aurum validates its manifest, configuration, backend routes, and interface metadata. Only a complete candidate replaces the previous version atomically.
If activation fails, the last healthy version remains active. The Kubernetes operator and GitOps connect the image version, configuration, and expected cluster state in one auditable process.
Backend plugin manifest
A plugin is a TypeScript module exporting a manifest defined through @aurum/backend-plugin-sdk. The contract contains the plugin version, SDK compatibility range, permission catalog, configuration schema, and endpoints:
import {
definePlugin,
type PluginManifest,
} from "@aurum/backend-plugin-sdk";
const READ = "contact-messages.read";
const WRITE = "contact-messages.write";
export const manifest: PluginManifest = definePlugin({
id: "contact-message",
name: "Contact",
version: "1.0.0",
sdkVersion: "^1.0.0",
permissions: [READ, WRITE],
configurationSchema: {
type: "object",
required: [
"retentionDays",
"publicRateLimit",
"allowedOrigins",
],
additionalProperties: false,
properties: {
retentionDays: { type: "integer" },
publicRateLimit: { type: "integer" },
allowedOrigins: { type: "array" },
},
},
backend: {
endpoints: [{
method: "GET",
path: "/api/contact-messages",
requireAuth: true,
requirePermission: [READ],
handler: async (request) =>
request.platform.storage.find(
"contactMessages",
{},
{ sort: { createdAt: -1 } },
),
}],
},
});
The registry rejects incompatible SDK ranges, duplicate permissions, invalid endpoint contracts, and plugin-owned runtime fields.
Capability API instead of raw infrastructure
Handlers receive narrow runtime-owned capabilities rather than unrestricted Fastify or MongoDB objects:
export interface PlatformCapabilities {
readonly pluginId: string;
readonly requestId: string;
readonly configuration:
Readonly<Record<string, unknown>>;
readonly audit: {
write(
event: string,
details?: Record<string, unknown>,
): Promise<void>;
};
readonly storage: {
find<T>(
collection: string,
filter?: Record<string, unknown>,
): Promise<T[]>;
insertOne<T>(
collection: string,
document: T,
): Promise<void>;
ensureIndex(
collection: string,
keys: Record<string, 1 | -1>,
options?: {
unique?: boolean;
expireAfterSeconds?: number;
},
): Promise<void>;
};
readonly rateLimit: {
consume(
subject: string,
policy: {
limit: number;
windowMilliseconds: number;
},
): Promise<boolean>;
};
}
Storage collections are automatically namespaced by plugin identity. storage.find("messages") cannot read the same logical collection owned by another extension.
Endpoint permissions and scope
An endpoint can require all declared capabilities or any one of them. scopeParam connects a route parameter to a scoped user grant:
{
method: "PATCH",
path: "/api/projects/:projectId/content/:id",
requireAuth: true,
requirePermission: [
"content.read",
"content.write",
],
permissionMode: "all",
scopeParam: "projectId",
handler: updateContent,
}
A content.write grant scoped to gardenia does not authorize writes to park-43. The gateway evaluates the grant before invoking plugin code.
Declarative plugin-set.yaml
The operator watches AurumPluginSet resources in aurum.dev/v1alpha1:
apiVersion: aurum.dev/v1alpha1
kind: AurumPluginSet
metadata:
name: portfolio-platform
namespace: gardenia
spec:
applicationRef:
targets:
- deployment: backend
container: backend
pluginMountPath: /app/plugins
- deployment: frontend
container: nginx
pluginMountPath: /usr/share/nginx/html/plugins
plugins:
- id: contact-message
image: europe-west1-docker.pkg.dev/platform/aurum/contact-message
version: 1.0.0
digest: sha256:2f36f2c7e5b7c18d81d73ca5e5a7e3b1d9b08a358af7f9b0b1f44f617db45a12
configuration:
retentionDays: 365
publicRateLimit: 5
publicRateLimitWindowSeconds: 60
allowedOrigins:
- https://gardenia.example
- id: real-estate
image: europe-west1-docker.pkg.dev/platform/aurum/real-estate
version: 1.0.0
tag: 1.0.0
Each plugin must use exactly one valid digest or tag. Production deployments can pin immutable digests. Duplicate IDs, invalid names, and relative mount paths fail validation before any Deployment is changed.
Deployment reconciliation
For every target, the operator creates a size-limited shared volume, mounts it read-only in the application container, generates controlled init containers, and adds a SHA-256 hash to the PodTemplate:
const pluginMount = {
name: "aurum-plugins",
mountPath: target.pluginMountPath,
readOnly: true,
};
template.spec.volumes = [{
name: "aurum-plugins",
emptyDir: { sizeLimit: "256Mi" },
}];
template.spec.initContainers = set.spec.plugins.map(
(plugin) => ({
name: `aurum-plugin-${plugin.id}`,
image: plugin.digest
? `${plugin.image}@${plugin.digest}`
: `${plugin.image}:${plugin.tag}`,
env: [
{ name: "PLUGIN_ID", value: plugin.id },
{ name: "PLUGIN_VERSION", value: plugin.version },
{
name: "PLUGIN_CONFIGURATION",
value: JSON.stringify(plugin.configuration ?? {}),
},
],
volumeMounts: [{
name: "aurum-plugins",
mountPath: "/plugins",
}],
}),
);
template.metadata.annotations[
"aurum.dev/plugin-hash"
] = sha256({ target, plugins: set.spec.plugins });
A hash change triggers a Kubernetes rollout. The custom resource reaches Ready after reconciliation; validation or mutation errors produce an Error phase with a diagnostic message.
Declaring Aurora content in Nuxt
Aurora does not scrape arbitrary DOM content. Editable points are explicit in website code:
<EditableText
translation-key="website.hero.title"
fallback="A home built around breathing room"
context="Primary headline of the hero section."
/>
The Nuxt integration supplies the publication scope and trusted parent origin:
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig();
const state = useState(
"aurora-published-state",
() => ({
mode: "view",
activeLocale:
config.public.auroraDefaultLocale,
translations: {},
}),
);
installAurora({
state,
applicationId:
config.public.auroraApplicationId,
parentOrigin: new URL(
config.public.auroraParentOrigin,
).origin,
});
});
The public Nuxt application fetches only the published snapshot for a tenant/application/environment/locale scope.
Result
The architecture allows the platform to grow in two independent directions: frontend teams retain full freedom over customer-facing design, while operational capabilities are reused as isolated products.
Aurum standardizes trust, contracts, and delivery. Plugins define the domain. Aurora lets editors work directly in the final experience.