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 ¶
const FileName = "aicoded.yaml"
FileName is the name of the permission list in an app's directory.
Variables ¶
This section is empty.
Functions ¶
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: the role rules a viewer must meet, whether a Guard on the page's path decides who sees each record, whether everyone the rules admit may see every record, and the page calls. Guard and Shared are never both set.
type Audience ¶
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 ¶
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" or "; shared", then "; 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 ¶
Data is one source of data the app reaches: sqldb, filestore:<name> or connector:<name>, with the classes of data it holds.
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 Parse ¶
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 ¶
Connectors returns the names of the connectors the app declares, sorted.
func (Manifest) Roles ¶
Roles returns every role the access and services sections name, sorted, without "*".
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.