Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions go/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package app
import (
core "dappco.re/go"
"dappco.re/go/config"
coreerr "dappco.re/go/log"
)

// AccessMode names the capability an action requires. The capital-letter
Expand Down Expand Up @@ -123,7 +122,7 @@ func (a AccessMode) String() string {
// }
func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if m == nil {
return coreerr.E("app.CheckAccess", "nil manifest", nil)
return core.E("app.CheckAccess", "nil manifest", nil)
}

switch mode {
Expand All @@ -137,7 +136,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if matchPrefix(m.Permissions.Read, arg) {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"read access to '"+arg+"' not declared in manifest.permissions.read",
nil,
Expand All @@ -156,7 +155,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if matchPrefix(manifestWriteList(m), arg) {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"write access to '"+arg+"' not declared in manifest.permissions.write",
nil,
Expand All @@ -168,7 +167,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if matchNet(m.Permissions.Net, arg) {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"net access to '"+arg+"' not declared in manifest.permissions.net",
nil,
Expand All @@ -177,7 +176,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if matchExact(m.Permissions.Run, arg) {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"run access to '"+arg+"' not declared in manifest.permissions.run",
nil,
Expand All @@ -186,7 +185,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if hasManifestStorePermission(m) {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"store access to '"+arg+"' not declared (set permissions.store: true in view.yaml)",
nil,
Expand All @@ -195,7 +194,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if m.Permissions.Notifications {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"notification access not declared (set permissions.notifications: true in view.yaml)",
nil,
Expand All @@ -204,7 +203,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if m.Permissions.Clipboard {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"clipboard read not declared (set permissions.clipboard: true in view.yaml)",
nil,
Expand All @@ -213,7 +212,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if m.Permissions.Clipboard {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"clipboard write not declared (set permissions.clipboard: true in view.yaml)",
nil,
Expand All @@ -222,7 +221,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if m.Permissions.Camera {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"camera access not declared (set permissions.camera: true in view.yaml)",
nil,
Expand All @@ -231,7 +230,7 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if m.Permissions.Microphone {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"microphone access not declared (set permissions.microphone: true in view.yaml)",
nil,
Expand All @@ -240,13 +239,13 @@ func CheckAccess(m *config.ViewManifest, mode AccessMode, arg string) error {
if hasManifestLocationPermission(m) {
return nil
}
return coreerr.E(
return core.E(
"app.CheckAccess",
"location access not declared (set permissions.device.location: true in view.yaml)",
nil,
)
default:
return coreerr.E("app.CheckAccess", "unknown access mode", nil)
return core.E("app.CheckAccess", "unknown access mode", nil)
}
}

Expand Down Expand Up @@ -317,7 +316,7 @@ func rejectPathTraversal(scope, arg string) error {
core.Contains(arg, "\\..\\") ||
core.HasSuffix(arg, "/..") ||
core.HasSuffix(arg, "\\..") {
return coreerr.E(
return core.E(
"app.CheckAccess",
scope+" access refused: path traversal in '"+arg+"'",
nil,
Expand Down Expand Up @@ -458,7 +457,7 @@ func ActionAccessMode(action string) (AccessMode, bool) {
// silently bypass the gate.
func CheckActionAccess(m *config.ViewManifest, action, arg string) error {
if m == nil {
return coreerr.E("app.CheckActionAccess", "nil manifest", nil)
return core.E("app.CheckActionAccess", "nil manifest", nil)
}
mode, ok := ActionAccessMode(action)
if !ok {
Expand Down
25 changes: 12 additions & 13 deletions go/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
core "dappco.re/go"
"dappco.re/go/config"
coreio "dappco.re/go/io"
coreerr "dappco.re/go/log"
)

// Mode selects which enforcement regime the boot uses.
Expand Down Expand Up @@ -245,38 +244,38 @@ func Boot(ctx context.Context, start string, opts ...Option) (*Instance, error)
// so a running app picks up YAML edits on reboot without a recompile.
manifest, root, err := discoverCompiled(o.Medium, start, o.Mode)
if err != nil {
return nil, coreerr.E("app.Boot", "discover failed", err)
return nil, core.E("app.Boot", "discover failed", err)
}
inst.Manifest = manifest
inst.Root = root

// Step 2 — Verify
trusted, err := resolveTrustedKeys(o)
if err != nil {
return nil, coreerr.E("app.Boot", "resolve trusted keys failed", err)
return nil, core.E("app.Boot", "resolve trusted keys failed", err)
}
if err := verify(&manifest, o.Mode, trusted); err != nil {
return nil, coreerr.E("app.Boot", "verify failed", err)
return nil, core.E("app.Boot", "verify failed", err)
}
if err := verifyAssetIntegrity(o.Medium, root, &manifest, o.Mode); err != nil {
return nil, coreerr.E("app.Boot", "asset integrity failed", err)
return nil, core.E("app.Boot", "asset integrity failed", err)
}

// Step 3 — Permissions
if err := permissions(c, &manifest, o.Mode); err != nil {
return nil, coreerr.E("app.Boot", "permission binding failed", err)
return nil, core.E("app.Boot", "permission binding failed", err)
}

// Step 4 — Modules
if err := modulesWithMode(ctx, c, &manifest, o.Mode); err != nil {
return nil, coreerr.E("app.Boot", "module load failed", err)
return nil, core.E("app.Boot", "module load failed", err)
}

// Step 5 — Layout. The resolved spec is stashed on the Instance so
// core/gui can compose the window without re-parsing the manifest.
spec, err := resolveLayout(c, &manifest)
if err != nil {
return nil, coreerr.E("app.Boot", "layout composition failed", err)
return nil, core.E("app.Boot", "layout composition failed", err)
}
inst.Layout = spec

Expand All @@ -288,7 +287,7 @@ func Boot(ctx context.Context, start string, opts ...Option) (*Instance, error)
ws, wsErr := OpenWorkspace(o.Medium, o.WorkspaceHome, manifest.Code)
if wsErr != nil {
if o.Mode == ModeProd {
return nil, coreerr.E("app.Boot", "workspace bootstrap failed", wsErr)
return nil, core.E("app.Boot", "workspace bootstrap failed", wsErr)
}
// Dev mode: workspace is best-effort so the boot keeps
// flowing when DIR_HOME is empty (CI containers, sandbox
Expand All @@ -302,10 +301,10 @@ func Boot(ctx context.Context, start string, opts ...Option) (*Instance, error)
// Step 6 — Config. Render after the workspace exists so template vars
// can hydrate from the runtime object store.
if err := renderManifestConfigTemplatesWithMode(c, &manifest, o.Medium, root, inst.Workspace, o.Mode); err != nil {
return nil, coreerr.E("app.Boot", "config template failed", err)
return nil, core.E("app.Boot", "config template failed", err)
}
if err := registerRuntimeActions(inst); err != nil {
return nil, coreerr.E("app.Boot", "runtime action registration failed", err)
return nil, core.E("app.Boot", "runtime action registration failed", err)
}

// Note: Step 7 (Start) is the caller's explicit trigger — Boot returns
Expand All @@ -322,7 +321,7 @@ func Boot(ctx context.Context, start string, opts ...Option) (*Instance, error)
// if !r.OK { core.Error("start failed", "err", r.Value) }
func (inst *Instance) Start(ctx context.Context) core.Result {
if inst == nil || inst.Core == nil {
return core.Result{Value: coreerr.E("app.Instance.Start", "nil instance", nil), OK: false}
return core.Result{Value: core.E("app.Instance.Start", "nil instance", nil), OK: false}
}
return start(ctx, inst)
}
Expand Down Expand Up @@ -355,7 +354,7 @@ func (inst *Instance) Start(ctx context.Context) core.Result {
// boot.
func (inst *Instance) Stop(ctx context.Context) core.Result {
if inst == nil || inst.Core == nil {
return core.Result{Value: coreerr.E("app.Instance.Stop", "nil instance", nil), OK: false}
return core.Result{Value: core.E("app.Instance.Stop", "nil instance", nil), OK: false}
}
return stop(ctx, inst)
}
43 changes: 19 additions & 24 deletions go/cmd/core-app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ package main
import (
"context"
"crypto/ed25519"
// AX-6 process-lifecycle exception: this file is the binary boundary.
// The CLI layer owns argv/signal wrappers, but core/app does
// not depend on that module in this lane, and go.mod is off-limits here.
"os"
"os/signal"
"syscall"

Expand All @@ -60,29 +56,29 @@ import (
)

func main() {
args := os.Args[1:]
args := core.Args()[1:]

// Subcommand dispatch — the first positional that matches a verb
// takes over. Falls through to the plain "boot" path otherwise so
// `core-app` without args still boots the CoreApp in the cwd.
if len(args) > 0 {
switch args[0] {
case "compile":
os.Exit(runCompile(args[1:]))
core.Exit(runCompile(args[1:]))
case "sign":
os.Exit(runSign(args[1:]))
core.Exit(runSign(args[1:]))
case "keygen":
os.Exit(runKeygen(args[1:]))
core.Exit(runKeygen(args[1:]))
case "pkg":
os.Exit(runPkg(args[1:]))
core.Exit(runPkg(args[1:]))
case "marketplace":
os.Exit(runMarketplace(args[1:]))
core.Exit(runMarketplace(args[1:]))
case "sdk":
os.Exit(runSDK(args[1:]))
core.Exit(runSDK(args[1:]))
case "run":
os.Exit(runInstalled(args[1:]))
core.Exit(runInstalled(args[1:]))
case "validate":
os.Exit(runValidate(args[1:]))
core.Exit(runValidate(args[1:]))
}
}

Expand Down Expand Up @@ -145,7 +141,7 @@ func runBootFromMode(mode app.Mode, start string, watch bool) {
inst, err := app.Boot(ctx, start, app.WithMode(mode))
if err != nil {
core.Error("boot failed", "start", start, "mode", mode.String(), "err", err)
os.Exit(1)
core.Exit(1)
}
core.Info("CoreApp booted",
"code", inst.Manifest.Code,
Expand All @@ -156,7 +152,7 @@ func runBootFromMode(mode app.Mode, start string, watch bool) {
)
if r := inst.Start(ctx); !r.OK {
core.Error("start failed", "err", r.Value)
os.Exit(2)
core.Exit(2)
}
if watch {
waitForReload(ctx, inst)
Expand All @@ -166,7 +162,7 @@ func runBootFromMode(mode app.Mode, start string, watch bool) {
// runBoot drives the "boot a CoreApp" path. Extracted from main so the
// subcommand dispatch reads cleanly.
//
// runBoot(os.Args[1:])
// runBoot(core.Args()[1:])
func runBoot(args []string) {
mode, start, watch := parseArgs(args)

Expand All @@ -176,7 +172,7 @@ func runBoot(args []string) {
inst, err := app.Boot(ctx, start, app.WithMode(mode))
if err != nil {
core.Error("boot failed", "start", start, "mode", mode.String(), "err", err)
os.Exit(1)
core.Exit(1)
}

core.Info("CoreApp booted",
Expand All @@ -189,7 +185,7 @@ func runBoot(args []string) {

if r := inst.Start(ctx); !r.OK {
core.Error("start failed", "err", r.Value)
os.Exit(2)
core.Exit(2)
}

if watch {
Expand Down Expand Up @@ -222,13 +218,12 @@ func waitForReload(ctx context.Context, inst *app.Instance) {
stopWatch := inst.Watch(ctx, app.WatchOptions{})
defer stopWatch()

sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(sigCh)
sigCtx, stopSignals := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer stopSignals()
core.Info("watching for changes — press Ctrl-C to stop")
select {
case <-ctx.Done():
case <-sigCh:
case <-sigCtx.Done():
}
if r := inst.Stop(ctx); !r.OK {
core.Error("stop failed", "err", r.Value)
Expand Down Expand Up @@ -272,11 +267,11 @@ func parseArgs(args []string) (mode app.Mode, start string, watch bool) {
core.Println(" run <app-code> boot an installed package by code")
core.Println(" pkg ... manage packages (list, info, wrap, install, remove, update)")
core.Println(" marketplace search/install/fetch from the marketplace")
os.Exit(0)
core.Exit(0)
default:
if core.HasPrefix(a, "-") {
core.Error("unknown flag", "flag", a)
os.Exit(64)
core.Exit(64)
}
start = a
}
Expand Down
5 changes: 2 additions & 3 deletions go/cmd/core-app/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import (
"context"
"os"

core "dappco.re/go"
"dappco.re/go/app"
Expand Down Expand Up @@ -1123,7 +1122,7 @@
//
// isExtractable("renderer.tar.gz") // true
// isExtractable("Renderer.7Z") // false
func isExtractable(path string) bool {

Check failure on line 1125 in go/cmd/core-app/pkg.go

View workflow job for this annotation

GitHub Actions / golangci-lint

func isExtractable is unused (unused)

Check failure on line 1125 in go/cmd/core-app/pkg.go

View workflow job for this annotation

GitHub Actions / golangci-lint

func isExtractable is unused (unused)
low := core.Lower(path)
for _, suffix := range []string{".zip", ".tar.gz", ".tgz", ".tar"} {
if core.HasSuffix(low, suffix) {
Expand Down Expand Up @@ -1859,11 +1858,11 @@

// ensureExit is an optional exit helper used only when the CLI wants
// to abort the process with a fixed code after writing context to
// stdout. Kept here (rather than calling os.Exit inline) so the test
// stdout. Kept here (rather than calling core.Exit inline) so the test
// harness can exercise the exit path without process-level side
// effects.
//
// ensureExit(64)
func ensureExit(code int) {
os.Exit(code)
core.Exit(code)
}
Loading
Loading