Skip to main content

Swift Customization

Keep provider, trusted actor and tenant, request policy, App Audit Sink, and optional telemetry in the application composition root. Generated queries and mutations receive only context. Do not add a second data-service argument or allow federation payloads to replace governance resources.

GeneratedRuntimeModule.module is a passive manifest. Install it during runtime assembly, then use context.ensureSchema(GeneratedRuntimeModule.module) only at an explicit startup or administrative boundary. Passing only module.entities bypasses module-owned root and constant bootstrap behavior. Module installation, request handling, health checks, and telemetry setup must not alter the production schema implicitly.

RuntimeTelemetry is no-op by default. If OpenTelemetry is enabled, the application owns exporters, processors, flush, and shutdown. Telemetry failure must not change a business result, and sampling must never suppress the App Audit Sink.

Worked Example: Trusted Runtime Composition​

public enum RuntimeCustomizationError: Error {
case missingTrustedTenant
case resourceBusy
}

public struct RuntimeComposition {
public let context: UserContext
public let dataService: SQLiteDataService
public let module: RuntimeModule
}

public func configuredRuntime(
databasePath: String,
module: RuntimeModule,
requestPolicy: RequestPolicy,
trustedTenant: String,
appAuditSink: any AuditSink,
telemetry: any RuntimeTelemetry = NoopRuntimeTelemetry()
) throws -> RuntimeComposition {
guard !trustedTenant.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
else { throw RuntimeCustomizationError.missingTrustedTenant }

let service = try SQLiteDataService(path: databasePath)
let context = UserContext(
actor: "teaql-application",
trustedTenant: trustedTenant,
queryExecutor: service,
mutationExecutor: service,
requestPolicy: requestPolicy,
auditSink: appAuditSink,
runtimeTelemetry: telemetry)
return RuntimeComposition(context: context, dataService: service, module: module)
}

public func readiness(_ runtime: RuntimeComposition) async throws {
guard let tenant = runtime.context.trustedTenant, !tenant.isEmpty
else { throw RuntimeCustomizationError.missingTrustedTenant }
try await runtime.context.ensureSchema(runtime.module)
}

The general Swift RequestPolicy hook applies to queries. Enforce Mutation tenant authorization at the application/provider/TFP boundary as well.

Runtime infrastructure​

Swift provides injectable LocalCache/LocalCache.shared and LocalLock/LocalLock.shared; both are process-local. The caller supplies a stable UUID owner to tryLock and unlock. TeaQL currently claims no Swift Remote Cache, Remote Lock, Nacos, or Consul adapter. See Cache, Lock, and Cloud Runtime Infrastructure for TTL, lease, readiness, and telemetry rules.

Worked Example: Local Cache and Lock​

Keep one stable owner UUID for the scope that owns the lock:

let cache = LocalCache.shared
let locks = LocalLock.shared
let lockOwner = UUID()

func currencyView(
context: UserContext,
tenant: String,
code: String
) async throws -> CurrencyView {
let cacheKey = "\(tenant):currency:\(code)"
if let value: CurrencyView = cache.get(cacheKey) { return value }

let lockKey = "\(tenant):currency-refresh:\(code)"
guard locks.tryLock(lockKey, owner: lockOwner, timeoutMillis: 250, expireMillis: 5_000)
else { throw RuntimeCustomizationError.resourceBusy }
defer { locks.unlock(lockKey, owner: lockOwner) }

if let value: CurrencyView = cache.get(cacheKey) { return value }
let value = try await loadAuthorizedCurrencyView(context, code)
cache.put(cacheKey, value: value, timeToLiveInSeconds: 300)
return value
}

RuntimeCustomizationError.resourceBusy is an application error case to add; it is not generated by TeaQL. Remove the cache entry after the corresponding audited Mutation commits.