Services

Publishing Services

How to publish TypeScript services in Kinotic using decorators.

Use the @Publish decorator to expose any TypeScript class as a remote service. The namespace you pass to @Publish combined with the class name forms the service identifier that callers use to reach it.

Basic Example

import { Publish, Version } from '@kinotic-ai/core'

@Version('1.0.0')
@Publish('com.example')
class GreetingService {
    hello(name: string): string {
        return `Hello, ${name}!`
    }

    add(a: number, b: number): number {
        return a + b
    }
}

This registers the service as com.example.GreetingService at version 1.0.0. Every public method on the class becomes a remotely callable operation.

Decorators

@Publish(namespace)

Marks a class for publication. The full service identifier becomes namespace.ClassName.

@Version(version)

Sets the semantic version for the service in X.Y.Z format. Callers can pin to a specific version when resolving the service.

@Scope

A property decorator that designates a field as the scope identifier. Scope narrows which service instance handles a request, which is useful for multi-tenant or per-device services.

import { Publish, Scope } from '@kinotic-ai/core'

@Publish('com.example')
class DeviceService {
    @Scope
    deviceId: string

    constructor(deviceId: string) {
        this.deviceId = deviceId
    }

    getStatus(): string {
        return `Status for device ${this.deviceId}`
    }
}

When a caller targets a specific scope (e.g., device-42), the platform routes the request to the instance whose deviceId matches.

@Context()

A parameter decorator that injects the request context into a method. The context carries information about the caller, such as the authenticated participant.

import { Publish, Context } from '@kinotic-ai/core'

@Publish('com.example')
class AuditService {
    logAction(action: string, @Context() ctx: any): void {
        console.log(`${ctx.participant.id} performed ${action}`)
    }
}

The @Context() parameter is invisible to callers. They do not pass it as an argument; the platform injects it automatically.

@AbacPolicy(expression)

Enforces attribute-based access control before the method is invoked. The expression can reference properties of the caller (participant) and the method arguments. Multiple @AbacPolicy decorators on the same method are combined with AND semantics -- all policies must pass.

import { Publish, AbacPolicy } from '@kinotic-ai/core'

@Publish('com.example')
class OrderService {
    @AbacPolicy("participant.roles contains 'finance' and order.amount < 50000")
    placeOrder(order: Order): void {
        // Only reached if caller has 'finance' role AND order under 50k
    }
}

If any policy expression evaluates to false, the platform rejects the call before it reaches the service.

Copyright © 2026