manifest

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package manifest reads and checks aicoded.yaml, the app's permission list.

Runners, the delivery pipeline and the aicoded CLI import it. App code may not: E-LINT-001 refuses the import.

Index

Examples

Constants

View Source
const FileName = "aicoded.yaml"

FileName is the name of the permission list in an app's directory.

Variables

This section is empty.

Functions

func ValidApp

func ValidApp(name string) bool

ValidApp reports whether name is a valid app name: 2-63 lowercase letters, digits and dashes, starting with a letter and ending with a letter or digit.

Types

type Access

type Access struct {
	Require []string `yaml:"require"`
	Guard   bool     `yaml:"guard"`
	Calls   []string `yaml:"calls"`
}

Access is one entry of the access section aicoded generate writes.

type Audience

type Audience struct {
	Internal []string `yaml:"internal"`
	External []string `yaml:"external"`
}

Audience is who may use the app: people of the company, as group:<name> or everyone, and outside people, as idp:<name> or magic-link.

type Change

type Change struct{ Field, Key, Before, After string }

Change is one difference between two permission lists. Key names the entry of a keyed field and is empty otherwise; Before is empty for what was added, After for what was removed.

func Diff

func Diff(before, after Manifest) []Change

Diff returns the differences between before and after, nil when there are none.

The changes come in the order of the fields, then by key. A list, such as egress, changes by each item removed or added, removals first, each sorted; a new order is no change, and a field left out equals an empty one. A keyed entry changes as a whole, written as text: a data source's classes, sorted; an access path's "require <rules>", then "; guard" and "; calls <names>" when they apply, its lists in written order; a served function's "callers <apps>", then "; require <rules>" and "; apps" when they apply, its lists sorted; a job's cron. The functions called from another app change one by one, keyed by that app.

Example

Diff lists what changed between two permission lists, field by field, as the platform's change records show it. A new order of a list is no change.

package main

import (
	"fmt"

	"aicoded.dev/framework/manifest"
)

func main() {
	before := manifest.Manifest{
		App:      "rooms",
		Access:   map[string]manifest.Access{"/rooms/{id}": {Require: []string{"staff"}}},
		Settings: []string{"greeting", "report_day"},
	}
	after := manifest.Manifest{
		App:      "rooms",
		Access:   map[string]manifest.Access{"/rooms/{id}": {Require: []string{"staff"}, Guard: true}},
		Egress:   []string{"api.partner.example"},
		Settings: []string{"report_day", "greeting"},
	}
	for _, c := range manifest.Diff(before, after) {
		fmt.Printf("%+v\n", c)
	}
}
Output:
{Field:access Key:/rooms/{id} Before:require staff After:require staff; guard}
{Field:egress Key: Before: After:api.partner.example}

type Data

type Data struct {
	Source  string   `yaml:"source"`
	Classes []string `yaml:"classes"`
}

Data is one source of data the app reaches: sqldb, filestore:<name> or connector:<name>, with the classes of data it holds.

type Email

type Email struct {
	From      string   `yaml:"from"`
	ToDomains []string `yaml:"to_domains"`
}

Email is the address the app sends mail from and the domains it may send to.

type Job

type Job struct {
	Cron string `yaml:"cron"`
	Name string `yaml:"job"`
}

Job is one scheduled job: its name and the cron expression, in UTC, of when it runs.

type Manifest

type Manifest struct {
	App       string            `yaml:"app"`
	Class     string            `yaml:"class"`
	Owner     string            `yaml:"owner"`
	Audience  Audience          `yaml:"audience"`
	Data      []Data            `yaml:"data"`
	Access    map[string]Access `yaml:"access"`
	Services  Services          `yaml:"services"`
	Egress    []string          `yaml:"egress"`
	Email     *Email            `yaml:"email"`
	Schedule  []Job             `yaml:"schedule"`
	Settings  []string          `yaml:"settings"`
	Secrets   []string          `yaml:"secrets"`
	Modules   []string          `yaml:"modules"`
	Size      string            `yaml:"size"`
	Resources string            `yaml:"resources"`
	TTL       string            `yaml:"ttl"`
}

Manifest is the permission list, aicoded.yaml. A field left out or empty is not stated.

func Load

func Load(path string) (Manifest, error)

Load reads and checks the manifest at path, as Parse does.

func Parse

func Parse(path string, data []byte) (Manifest, error)

Parse checks the manifest data and returns it. Path is used only in the positions of problems. It reports every problem it finds as one coded error each: its error unwraps, with Unwrap() []error, to them, sorted by line. Data that is not one YAML document of the expected shape, or that uses an anchor, an alias or a merge key, is not checked any further.

Example

Parse checks a permission list and returns its fields. A list with problems returns every problem, each with a code and its position.

package main

import (
	"fmt"

	"aicoded.dev/framework/manifest"
)

func main() {
	m, err := manifest.Parse(manifest.FileName, []byte("app: rooms\negress: [api.partner.example]\n"))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(m.Egress)
}
Output:
[api.partner.example]

func (Manifest) Connectors

func (m Manifest) Connectors() []string

Connectors returns the names of the connectors the app declares, sorted.

func (Manifest) Roles

func (m Manifest) Roles() []string

Roles returns every role the access and services sections name, sorted, without "*".

func (Manifest) SQLDB

func (m Manifest) SQLDB() bool

SQLDB reports whether the app declares its SQL database.

func (Manifest) Stores

func (m Manifest) Stores() []string

Stores returns the names of the file stores the app declares, sorted.

type Serve

type Serve struct {
	Callers []string `yaml:"callers"`
	Require []string `yaml:"require,omitempty"`
	Apps    bool     `yaml:"apps,omitempty"`
}

Serve says who may call one function the app serves: the calling apps, the role rules a viewer must meet, written as in the access section, and whether a calling app may call it with no viewer. A function without role rules takes no call on behalf of a viewer.

type Services

type Services struct {
	Calls  map[string][]string `yaml:"calls"`
	Serves map[string]Serve    `yaml:"serves"`
}

Services is the services section aicoded generate writes: the functions of other apps this app calls, by app, and the functions it serves to other apps, by name.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL