fix(rfc): update stale specs to match v0.8.0 implementation
- Version header: v0.7.0+ → v0.8.0 - Section 2.4: type Task any removed, PERFORM replaced by PerformAsync - Section 3.3+3.5: Startable/Stoppable return Result not error - Section 4.3: PERFORM → PerformAsync with named action + Options - Section 1.3: Added Process, API, Action, Task, Entitled, RegistryOf - Section 8: Added WriteAtomic, NewUnrestricted, Root - Section 9: Added Command.Managed field - Description updated to include "permission" Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
390b392dec
commit
a26d9437bb
1 changed files with 53 additions and 31 deletions
84
docs/RFC.md
84
docs/RFC.md
|
|
@ -1,12 +1,12 @@
|
|||
# CoreGO API Contract — RFC Specification
|
||||
|
||||
> `dappco.re/go/core` — Dependency injection, service lifecycle, and message-passing framework.
|
||||
> `dappco.re/go/core` — Dependency injection, service lifecycle, permission, and message-passing framework.
|
||||
> This document is the authoritative API contract. An agent should be able to write a service
|
||||
> that registers with Core from this document alone.
|
||||
|
||||
**Status:** Living document
|
||||
**Module:** `dappco.re/go/core`
|
||||
**Version:** v0.7.0+
|
||||
**Version:** v0.8.0
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -42,19 +42,25 @@ Run() → ServiceStartup() → Cli.Run() → ServiceShutdown()
|
|||
Every subsystem is accessed via a method on Core:
|
||||
|
||||
```go
|
||||
c.Options() // *Options — input configuration
|
||||
c.App() // *App — application metadata (name, version)
|
||||
c.Config() // *Config — runtime settings, feature flags
|
||||
c.Data() // *Data — embedded assets mounted by packages
|
||||
c.Drive() // *Drive — transport handles (API, MCP, SSH)
|
||||
c.Fs() // *Fs — filesystem I/O (sandboxable)
|
||||
c.Cli() // *Cli — CLI command framework
|
||||
c.IPC() // *Ipc — message bus internals
|
||||
c.I18n() // *I18n — internationalisation
|
||||
c.Error() // *ErrorPanic — panic recovery
|
||||
c.Log() // *ErrorLog — structured logging
|
||||
c.Context() // context.Context — Core's lifecycle context
|
||||
c.Env(key) // string — environment variable (cached at init)
|
||||
c.Options() // *Options — input configuration
|
||||
c.App() // *App — application metadata (name, version)
|
||||
c.Config() // *Config — runtime settings, feature flags
|
||||
c.Data() // *Data — embedded assets (Registry[*Embed])
|
||||
c.Drive() // *Drive — transport handles (Registry[*DriveHandle])
|
||||
c.Fs() // *Fs — filesystem I/O (sandboxable)
|
||||
c.Cli() // *Cli — CLI command framework
|
||||
c.IPC() // *Ipc — message bus internals
|
||||
c.I18n() // *I18n — internationalisation
|
||||
c.Error() // *ErrorPanic — panic recovery
|
||||
c.Log() // *ErrorLog — structured logging
|
||||
c.Process() // *Process — managed execution (Action sugar)
|
||||
c.API() // *API — remote streams (protocol handlers)
|
||||
c.Action(name) // *Action — named callable (register/invoke)
|
||||
c.Task(name) // *Task — composed Action sequence
|
||||
c.Entitled(name) // Entitlement — permission check
|
||||
c.RegistryOf(n) // *Registry — cross-cutting queries
|
||||
c.Context() // context.Context
|
||||
c.Env(key) // string — environment variable (cached at init)
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -124,16 +130,17 @@ return core.Result{Value: err, OK: false}
|
|||
|
||||
No generics on Result. Type-assert the Value when needed. This is deliberate — `Result` is universal across all subsystems without carrying type parameters.
|
||||
|
||||
### 2.4 Message, Query, Task
|
||||
### 2.4 Message, Query
|
||||
|
||||
IPC type aliases — all are `any` at the type level, distinguished by usage:
|
||||
IPC type aliases for the broadcast/request system:
|
||||
|
||||
```go
|
||||
type Message any // broadcast via ACTION — fire and forget
|
||||
type Query any // request/response via QUERY — returns first handler's result
|
||||
type Task any // work unit via PERFORM — tracked with progress
|
||||
```
|
||||
|
||||
For tracked work, use named Actions: `c.PerformAsync("action.name", opts)`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Service System
|
||||
|
|
@ -179,8 +186,8 @@ func (s *MyService) doSomething() {
|
|||
|
||||
`WithService` reflects on the returned instance to discover:
|
||||
- **Package name** → service name (from reflect type path)
|
||||
- **Startable interface** → `OnStartup(ctx) error` called during `ServiceStartup`
|
||||
- **Stoppable interface** → `OnShutdown(ctx) error` called during `ServiceShutdown`
|
||||
- **Startable interface** → `OnStartup(ctx) Result` called during `ServiceStartup`
|
||||
- **Stoppable interface** → `OnShutdown(ctx) Result` called during `ServiceShutdown`
|
||||
- **HandleIPCEvents method** → auto-registered as IPC handler
|
||||
|
||||
### 3.4 Retrieval
|
||||
|
|
@ -203,11 +210,11 @@ names := c.Services() // []string
|
|||
|
||||
```go
|
||||
type Startable interface {
|
||||
OnStartup(ctx context.Context) error
|
||||
OnStartup(ctx context.Context) Result
|
||||
}
|
||||
|
||||
type Stoppable interface {
|
||||
OnShutdown(ctx context.Context) error
|
||||
OnShutdown(ctx context.Context) Result
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -258,20 +265,19 @@ c.RegisterQuery(func(c *core.Core, q core.Query) core.Result {
|
|||
})
|
||||
```
|
||||
|
||||
### 4.3 PERFORM (tracked task)
|
||||
### 4.3 PerformAsync (background action)
|
||||
|
||||
```go
|
||||
// Execute with progress tracking
|
||||
c.PERFORM(MyTask{Data: payload})
|
||||
// Execute a named action in background with progress tracking
|
||||
r := c.PerformAsync("agentic.dispatch", opts)
|
||||
taskID := r.Value.(string)
|
||||
|
||||
// Register task handler
|
||||
c.RegisterTask(func(c *core.Core, t core.Task) core.Result {
|
||||
// do work, report progress
|
||||
c.Progress(taskID, 0.5, "halfway done", t)
|
||||
return core.Result{Value: output, OK: true}
|
||||
})
|
||||
// Report progress
|
||||
c.Progress(taskID, 0.5, "halfway done", "agentic.dispatch")
|
||||
```
|
||||
|
||||
Broadcasts `ActionTaskStarted`, `ActionTaskProgress`, `ActionTaskCompleted` as ACTION messages.
|
||||
|
||||
---
|
||||
|
||||
## 5. Config
|
||||
|
|
@ -369,11 +375,18 @@ r := fs.Append(path) // Result{Value: io.WriteCloser}
|
|||
r := fs.ReadStream(path) // Result{Value: io.ReadCloser}
|
||||
r := fs.WriteStream(path) // Result{Value: io.WriteCloser}
|
||||
|
||||
// Atomic write (write-to-temp-then-rename, safe for concurrent readers)
|
||||
r := fs.WriteAtomic(path, content)
|
||||
|
||||
// Delete
|
||||
r := fs.Delete(path) // single file
|
||||
r := fs.DeleteAll(path) // recursive
|
||||
r := fs.Rename(old, new)
|
||||
r := fs.Stat(path) // Result{Value: os.FileInfo}
|
||||
|
||||
// Sandbox control
|
||||
fs.Root() // sandbox root path
|
||||
fs.NewUnrestricted() // Fs with root "/" — full access
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -404,6 +417,15 @@ func (s *MyService) cmdIssueGet(opts core.Options) core.Result {
|
|||
|
||||
Path = command hierarchy. `issue/get` becomes `myapp issue get` in CLI.
|
||||
|
||||
Managed commands have lifecycle provided by go-process:
|
||||
|
||||
```go
|
||||
c.Command("serve", core.Command{
|
||||
Action: handler,
|
||||
Managed: "process.daemon", // go-process provides start/stop/restart
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Error Handling
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue