Update version

Update version

@0x99f9db243de9f4eb;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "qkgkaxfqhgsff8zgx2f4nf1a8xvmpte6wa19egmfkk06mzt7e8dh",
  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in your app package to tell Sandstorm
    # about your app.

    appTitle = (defaultText = "Let's Chat"),

    appVersion = 4,  # Increment this for every release.

    appMarketingVersion = (defaultText = "0.1.0"),

    actions = [
      # Define your "new document" handlers here.
      ( title = (defaultText = "New Let's Chat"),
        command = .myCommand
        # The command to run when starting for the first time. (".myCommand"
        # is just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.
  ),

  sourceMap = (
    # Here we defined where to look for files to copy into your package. The
    # `spk dev` command actually figures out what files your app needs
    # automatically by running it on a FUSE filesystem. So, the mappings
    # here are only to tell it where to find files that the app wants.
    searchPath = [
      ( sourcePath = "." ),  # Search this directory first.
      ( sourcePath = "hosts", packagePath = "etc/hosts" ),  # Search this directory first.
      ( sourcePath = "/",    # Then search the system root directory.
        hidePaths = [ "home", "proc", "sys",
                      "etc/passwd", "etc/hosts", "etc/host.conf",
                      "etc/nsswitch.conf", "etc/resolv.conf" ]
        # You probably don't want the app pulling files from these places,
        # so we hide them. Note that /dev, /var, and /tmp are implicitly
        # hidden because Sandstorm itself provides them.
      )
    ]
  ),

  fileList = "sandstorm-files.list",
  # `spk dev` will write a list of all the files your app uses to this file.
  # You should review it later, before shipping your app.

  alwaysInclude = ["templates"]
  # Fill this list with more names of files or directories that should be
  # included in your package, even if not listed in sandstorm-files.list.
  # Use this to force-include stuff that you know you need but which may
  # not have been detected as a dependency during `spk dev`. If you list
  # a directory here, its entire contents will be included recursively.
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "33411", "--", "bash", "run_grain.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);

@0x99f9db243de9f4eb;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "qkgkaxfqhgsff8zgx2f4nf1a8xvmpte6wa19egmfkk06mzt7e8dh",
  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in your app package to tell Sandstorm
    # about your app.

    appTitle = (defaultText = "Let's Chat"),

    appVersion = 0,  # Increment this for every release.

    appMarketingVersion = (defaultText = "0.1.0"),

    actions = [
      # Define your "new document" handlers here.
      ( title = (defaultText = "New Let's Chat"),
        command = .myCommand
        # The command to run when starting for the first time. (".myCommand"
        # is just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.
  ),

  sourceMap = (
    # Here we defined where to look for files to copy into your package. The
    # `spk dev` command actually figures out what files your app needs
    # automatically by running it on a FUSE filesystem. So, the mappings
    # here are only to tell it where to find files that the app wants.
    searchPath = [
      ( sourcePath = "." ),  # Search this directory first.
      ( sourcePath = "hosts", packagePath = "etc/hosts" ),  # Search this directory first.
      ( sourcePath = "/",    # Then search the system root directory.
        hidePaths = [ "home", "proc", "sys",
                      "etc/passwd", "etc/hosts", "etc/host.conf",
                      "etc/nsswitch.conf", "etc/resolv.conf" ]
        # You probably don't want the app pulling files from these places,
        # so we hide them. Note that /dev, /var, and /tmp are implicitly
        # hidden because Sandstorm itself provides them.
      )
    ]
  ),

  fileList = "sandstorm-files.list",
  # `spk dev` will write a list of all the files your app uses to this file.
  # You should review it later, before shipping your app.

  alwaysInclude = []
  # Fill this list with more names of files or directories that should be
  # included in your package, even if not listed in sandstorm-files.list.
  # Use this to force-include stuff that you know you need but which may
  # not have been detected as a dependency during `spk dev`. If you list
  # a directory here, its entire contents will be included recursively.
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "33411", "--", "bash", "run_grain.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);


first draft of capnProto schema. Does not yet compile

@0xfb2d77234707241e; # unique file ID, generated by `capnp id`
using Go = import "go.capnp";
$Go.package("proto");
$Go.import("proto");

struct RainsMessage  {
    #RainsMessage contains the data of a message
	Token           @0 :Data;
	Content         @1 :List(MessageSection);
	Signatures      @2 :List(Signature);
	Capabilities    @3 :List(Text);
}

interface MessageSection  {
}

const NoCapability :Text = "";
const TLSOverTCP :Text = "urn:x-rains:tlssrv";

interface MessageSectionWithSig extends(MessageSection) {
    #MessageSectionWithSig can be either an Assertion, Shard or Zone
	Sigs            @0 () -> (sig :Signature);
	AddSig          @1 (sig :Signature);
	DeleteSig       @2 (int :Int32);
	DeleteAllSigs   @3 ();
    #TODO CFE what is the syntax of a method without arguments
	GetContext      @4 () -> (context :Text);
	GetSubjectZone  @5 () -> (zone :Text);
	CreateStub      @6 () -> (section :MessageSectionWithSig);
	ValidFrom       @7 () -> (validFrom :int64);
	ValidUntil      @8 () -> (validUntil :int64);
	Hash            @9 () -> (hash :Text);
	Interval        @10 :Interval;
}

interface Interval  {
    #Interval defines an interval over strings
	Begin   @0 () -> (begin :Text)
	End     @1 () -> (end :Text)
}

interface Hashable  {
    #Hashable can be implemented by objects that are not natively hashable.
	Hash @0 () -> (hash :Text);
}

struct AssertionSection  {
    #AssertionSection contains information about the assertion
	SubjectName @0 :Text;
	Content     @1 :List(Object);
	Signatures  @2 :List(Signature);
	SubjectZone @3 :Text;
	Context     @4 :Text;
}

struct ShardSection  {
    #ShardSection contains information about the shard
	Content     @0 :List(AssertionSection);
	Signatures  @1 :List(Signature);
	SubjectZone @2 :Text;
	Context     @3 :Text;
	RangeFrom   @4 :Text;
	RangeTo     @5 :Text;
}

struct ZoneSection  {
    #ZoneSection contains information about the zone
	Signatures  @0  :List(Signature);
	SubjectZone @1  :Text;
	Context     @2  :Text;
	Content     @3  :List(MessageSectionWithSig);
}

struct QuerySection  {
    #QuerySection contains information about the query
	Token   @0      :Data;
	Name    @1      :Text;
	Context @2      :Text;
	Type    @3      :ObjectType;
	Expires @4      :Int64; #time when this query expires represented as the number of seconds elapsed since January 1, 1970 UTC
	Options @5      :List(QueryOption);
}

enum QueryOption {
	MinE2ELatency            @1;
	MinLastHopAnswerSize     @2;
	MinInfoLeakage           @3;
	CachedAnswersOnly        @4;
	ExpiredAssertionsOk      @5;
	TokenTracing             @6;
	NoVerificationDelegation @7;
	NoProactiveCaching       @8;
}

enum ObjectType {
	OTName        @1;
	OTIP6Addr     @2;
	OTIP4Addr     @3;
	OTRedirection @4;
	OTDelegation  @5;
	OTNameset     @6;
	OTCertInfo    @7;
	OTServiceInfo @8;
	OTRegistrar   @9;
	OTRegistrant  @10;
	OTInfraKey    @11;
	OTExtraKey    @12;
}

struct SubjectAddr  {
	AddressFamily @0    :Text;
	PrefixLength  @1    :UInt32;
	Address       @2    :Text;
}

struct AddressAssertionSection  {
    #AddressAssertionSection contains information about the address assertion
	SubjectAddr @0  :SubjectAddr;
	Content     @1  :List(Object);
	Signatures  @2  :List(Signature);
	Context     @3  :Text;
}

struct AddressZoneSection  {
    #AddressZoneSection contains information about the address zone
	SubjectAddr @0  :SubjectAddr;
	Signatures  @1  :List:(Signature);
	Context     @2  :Text;
	Content     @3  :List(AddressAssertionSection);
}

struct AddressQuerySection  {
    #AddressQuerySection contains information about the address query
	SubjectAddr @0 :SubjectAddr;
	Token       @1 :Data;
	Context     @2 :Text;
	Types       @3 :List(Int32);
	Expires     @4 :Int64
	Options     @5 :List(QueryOption);
}

struct NotificationSection  {
    #NotificationSection contains information about the notification
	Token @0    :Data;
	Type  @1    :NotificationType;
	Data  @2    :Text;
}

enum NotificationType {
	Heartbeat          @0;
	CapHashNotKnown    @1;
	BadMessage         @2;
	RcvInconsistentMsg @3;
	NoAssertionsExist  @4;
	MsgTooLarge        @5;
	UnspecServerErr    @6;
	ServerNotCapable   @7;
	NoAssertionAvail   @8;
}

struct Signature  {
    #Signature on a Rains message or section
	KeySpace   @0 :KeySpaceID;
	Algorithm  @1 :SignatureAlgorithmType;
	ValidSince @2 :Int64;
	ValidUntil @3 :Int64;
	Data       @4 :Data;
}

enum KeySpaceID {
#KeySpaceID identifies a key space
	RainsKeySpace @0;
}

enum SignatureAlgorithmType {
#SignatureAlgorithmType specifies a signature algorithm type
	Ed25519  @0;
	Ed448    @1;
	Ecdsa256 @2;
	Ecdsa384 @3;
}

enum HashAlgorithmType {
#HashAlgorithmType specifies a hash algorithm type
	NoHashAlgo @0;
	Sha256     @1;
	Sha384     @2;
	Sha512     @3;
}

struct PublicKey  {
    #PublicKey contains information about a public key
	Type       @0 :SignatureAlgorithmType;
	Key        @1 :Data;
	ValidFrom  @2 :Int64;
	ValidUntil @3 :Int64;
}

struct CertificateObject  {
    #CertificateObject contains certificate information
	Type     @0 :ProtocolType;
	Usage    @1 :CertificateUsage;
	HashAlgo @2 :HashAlgorithmType;
	Data     @3 :Data;
}

enum ProtocolType {
	PTUnspecified @0;
	PTTLS         @1;
}

enum CertificateUsage {
	CUTrustAnchor @0;
	CUEndEntity   @1;
}

struct ServiceInfo  {
    #ServiceInfo contains information how to access a named service
	Name     @0 :Text;
	Port     @1 :UInt16;
	Priority @2 :UInt32;
}

struct Object  {
    #Object is a container for different values determined by the given type.
	Type  @0    :ObjectType;
	Value @1    :Data;
}

struct RainsMessage  {
    #RainsMessage contains the data of a message
	Token  @0 :Data;
	Content @1 :List(MessageSection);
	Signatures @2 :List(Signature);
	Capabilities @3 :List(Text);
}

interface MessageSection  {
}

const NoCapability :Text = "";
const TLSOverTCP :Text = "urn:x-rains:tlssrv";

interface MessageSectionWithSig extends(MessageSection) {
    #MessageSectionWithSig can be either an Assertion, Shard or Zone
	Sigs @0 () -> (sig :Signature);
	AddSig @0 (sig :Signature);
	DeleteSig @0 (int :Int32);
	DeleteAllSigs @0 ();
    #TODO CFE what is the syntax of a method without arguments
	GetContext @0 () -> (context :Text);
	GetSubjectZone @0 () -> (zone :Text);
	CreateStub @0 () -> (section :MessageSectionWithSig);
	ValidFrom @0 () -> (validFrom :int64);
	ValidUntil @0 () -> (validUntil :int64);
	Hash @0 () -> (hash :Text);
	Interval :Interval
}

type Interval interface {
    #Interval defines an interval over strings
	Begin() string
	End() string
}

//TotalInterval is an interval over the whole namespace
type TotalInterval struct{}

func (t TotalInterval) Begin() string {
	return ""
}

func (t TotalInterval) End() string {
	return ""
}

//StringInterval implements Interval for a single string value
type StringInterval struct {
	Name string
}

func (s StringInterval) Begin() string {
	return s.Name
}

func (s StringInterval) End() string {
	return s.Name
}

//Hashable can be implemented by objects that are not natively hashable.
type Hashable interface {
	//Hash must return a string uniquely identifying the object
	Hash() string
}

//AssertionSection contains information about the assertion
type AssertionSection struct {
	SubjectName string
	Content     []Object
	Signatures  []Signature
	SubjectZone string
	Context     string
}

//Sigs return the assertion's signatures
func (a *AssertionSection) Sigs() []Signature {
	return a.Signatures
}

//AddSig adds the given signature
func (a *AssertionSection) AddSig(sig Signature) {
	a.Signatures = append(a.Signatures, sig)
}

//DeleteSig deletes ith signature
func (a *AssertionSection) DeleteSig(i int) {
	a.Signatures = append(a.Signatures[:i], a.Signatures[i+1:]...)
}

//DeleteAllSigs deletes all signatures
func (a *AssertionSection) DeleteAllSigs() {
	a.Signatures = []Signature{}
}

//GetContext returns the context of the assertion
func (a *AssertionSection) GetContext() string {
	return a.Context
}

//GetSubjectZone returns the zone of the assertion
func (a *AssertionSection) GetSubjectZone() string {
	return a.SubjectZone
}

//CreateStub creates a copy of the assertion without the signatures.
func (a *AssertionSection) CreateStub() MessageSectionWithSig {
	stub := &AssertionSection{}
	*stub = *a
	stub.DeleteAllSigs()
	return stub
}

//Begin returns the begining of the interval of this assertion.
func (a *AssertionSection) Begin() string {
	return a.SubjectName
}

//End returns the end of the interval of this assertion.
func (a *AssertionSection) End() string {
	return a.SubjectName
}

//ValidFrom returns the earliest validFrom date of all contained signatures
func (a *AssertionSection) ValidFrom() int64 {
	valid := a.Signatures[0].ValidSince
	for _, sig := range a.Signatures[1:] {
		if sig.ValidSince < valid {
			valid = sig.ValidSince
		}
	}
	return valid
}

//ValidUntil returns the latest validUntil date of all contained signatures
func (a *AssertionSection) ValidUntil() int64 {
	//FIXME CFE this is not correct. There might be a time interval between several signatures during which this assertion is not valid.
	//Return the latest time which is reachable with all contained signatures without gaps in between
	valid := a.Signatures[0].ValidUntil
	for _, sig := range a.Signatures[1:] {
		if sig.ValidSince > valid {
			valid = sig.ValidSince
		}
	}
	return valid
}

//Hash returns a string containing all information uniquely identifying an assertion.
func (a *AssertionSection) Hash() string {
	return fmt.Sprintf("%s_%s_%s_%v_%v", a.Context, a.SubjectZone, a.SubjectName, a.Content, a.Signatures)
}

//EqualContextZoneName return true if the given assertion has the same context, zone, name.
func (a *AssertionSection) EqualContextZoneName(assertion *AssertionSection) bool {
	return a.Context == assertion.Context &&
		a.SubjectZone == assertion.SubjectZone &&
		a.SubjectName == assertion.SubjectName
}

//ShardSection contains information about the shard
type ShardSection struct {
	Content     []*AssertionSection
	Signatures  []Signature
	SubjectZone string
	Context     string
	RangeFrom   string
	RangeTo     string
}

//Sigs return the shard's signatures
func (s *ShardSection) Sigs() []Signature {
	return s.Signatures
}

//AddSig adds the given signature
func (s *ShardSection) AddSig(sig Signature) {
	s.Signatures = append(s.Signatures, sig)
}

//DeleteSig deletes ith signature
func (s *ShardSection) DeleteSig(i int) {
	s.Signatures = append(s.Signatures[:i], s.Signatures[i+1:]...)
}

//DeleteAllSigs deletes all signatures
func (s *ShardSection) DeleteAllSigs() {
	s.Signatures = []Signature{}
	for _, assertion := range s.Content {
		assertion.DeleteAllSigs()
	}
}

//GetContext returns the context of the shard
func (s *ShardSection) GetContext() string {
	return s.Context
}

//GetSubjectZone returns the zone of the shard
func (s *ShardSection) GetSubjectZone() string {
	return s.SubjectZone
}

//CreateStub creates a copy of the shard and its contained assertions without the signatures.
func (s *ShardSection) CreateStub() MessageSectionWithSig {
	stub := &ShardSection{}
	*stub = *s
	stub.Content = []*AssertionSection{}
	for _, assertion := range s.Content {
		stub.Content = append(stub.Content, assertion.CreateStub().(*AssertionSection))
	}
	stub.DeleteAllSigs()
	return stub
}

//Begin returns the begining of the interval of this shard.
func (s *ShardSection) Begin() string {
	return s.RangeFrom
}

//End returns the end of the interval of this shard.
func (s *ShardSection) End() string {
	return s.RangeTo
}

//ValidFrom returns the earliest validFrom date of all contained signatures
func (s *ShardSection) ValidFrom() int64 {
	valid := s.Signatures[0].ValidSince
	for _, sig := range s.Signatures[1:] {
		if sig.ValidSince < valid {
			valid = sig.ValidSince
		}
	}
	return valid
}

//ValidUntil returns the latest validUntil date of all contained signatures
func (s *ShardSection) ValidUntil() int64 {
	//FIXME CFE this is not correct. There might be a time interval between several signatures during which this assertion is not valid.
	//Return the latest time which is reachable with all contained signatures without gaps in between
	valid := s.Signatures[0].ValidUntil
	for _, sig := range s.Signatures[1:] {
		if sig.ValidSince > valid {
			valid = sig.ValidSince
		}
	}
	return valid
}

//Hash returns a string containing all information uniquely identifying a shard.
func (s *ShardSection) Hash() string {
	aHashes := ""
	for _, a := range s.Content {
		aHashes += a.Hash()
	}
	return fmt.Sprintf("%s_%s_%s_%s_%s_%v", s.Context, s.SubjectZone, s.RangeFrom, s.RangeTo, aHashes, s.Signatures)
}

//ZoneSection contains information about the zone
type ZoneSection struct {
	Signatures  []Signature
	SubjectZone string
	Context     string
	Content     []MessageSectionWithSig
}

//Sigs return the zone's signatures
func (z *ZoneSection) Sigs() []Signature {
	return z.Signatures
}

//AddSig adds the given signature
func (z *ZoneSection) AddSig(sig Signature) {
	z.Signatures = append(z.Signatures, sig)
}

//DeleteSig deletes ith signature
func (z *ZoneSection) DeleteSig(i int) {
	z.Signatures = append(z.Signatures[:i], z.Signatures[i+1:]...)
}

//DeleteAllSigs deletes all signatures
func (z *ZoneSection) DeleteAllSigs() {
	z.Signatures = []Signature{}
	for _, section := range z.Content {
		switch section := section.(type) {
		case *AssertionSection, *ShardSection:
			section.DeleteAllSigs()
		default:
			log.Warn("Unknown message section", "messageSection", section)
		}
	}
}

//GetContext returns the context of the zone
func (z *ZoneSection) GetContext() string {
	return z.Context
}

//GetSubjectZone returns the zone of the zone
func (z *ZoneSection) GetSubjectZone() string {
	return z.SubjectZone
}

//CreateStub creates a copy of the zone and the contained shards and assertions without the signatures.
func (z *ZoneSection) CreateStub() MessageSectionWithSig {
	stub := &ZoneSection{}
	*stub = *z
	stub.Content = []MessageSectionWithSig{}
	for _, section := range z.Content {
		switch section := section.(type) {
		case *AssertionSection, *ShardSection:
			stub.Content = append(stub.Content, section.CreateStub())
		default:
			log.Warn("Unknown message section", "messageSection", section)
		}
	}
	stub.DeleteAllSigs()
	return stub
}

//Begin returns the begining of the interval of this zone.
func (z *ZoneSection) Begin() string {
	return ""
}

//End returns the end of the interval of this zone.
func (z *ZoneSection) End() string {
	return ""
}

//ValidFrom returns the earliest validFrom date of all contained signatures
func (z *ZoneSection) ValidFrom() int64 {
	valid := z.Signatures[0].ValidSince
	for _, sig := range z.Signatures[1:] {
		if sig.ValidSince < valid {
			valid = sig.ValidSince
		}
	}
	return valid
}

//ValidUntil returns the latest validUntil date of all contained signatures
func (z *ZoneSection) ValidUntil() int64 {
	//FIXME CFE this is not correct. There might be a time interval between several signatures during which this assertion is not valid.
	//Return the latest time which is reachable with all contained signatures without gaps in between
	valid := z.Signatures[0].ValidUntil
	for _, sig := range z.Signatures[1:] {
		if sig.ValidSince > valid {
			valid = sig.ValidSince
		}
	}
	return valid
}

//Hash returns a string containing all information uniquely identifying a shard.
func (z *ZoneSection) Hash() string {
	contentHashes := ""
	for _, v := range z.Content {
		switch v := v.(type) {
		case *AssertionSection, *ShardSection:
			contentHashes += v.Hash()
		default:
			log.Warn(fmt.Sprintf("not supported zone section content, must be assertion or shard, got %T", v))
		}
	}
	return fmt.Sprintf("%s_%s_%s_%v", z.Context, z.SubjectZone, contentHashes, z.Signatures)
}

//QuerySection contains information about the query
type QuerySection struct {
	//Mandatory
	Token   Token
	Name    string
	Context string
	Type    ObjectType
	Expires int64 //time when this query expires represented as the number of seconds elapsed since January 1, 1970 UTC

	//Optional
	Options []QueryOption
}

//ContainsOption returns true if the query contains the given query option.
func (q QuerySection) ContainsOption(option QueryOption) bool {
	for _, opt := range q.Options {
		if opt == option {
			return true
		}
	}
	return false
}

type QueryOption int

const (
	MinE2ELatency            QueryOption = 1
	MinLastHopAnswerSize     QueryOption = 2
	MinInfoLeakage           QueryOption = 3
	CachedAnswersOnly        QueryOption = 4
	ExpiredAssertionsOk      QueryOption = 5
	TokenTracing             QueryOption = 6
	NoVerificationDelegation QueryOption = 7
	NoProactiveCaching       QueryOption = 8
)

type ObjectType int

func (o ObjectType) String() string {
	return strconv.Itoa(int(o))
}

const (
	OTName        ObjectType = 1
	OTIP6Addr     ObjectType = 2
	OTIP4Addr     ObjectType = 3
	OTRedirection ObjectType = 4
	OTDelegation  ObjectType = 5
	OTNameset     ObjectType = 6
	OTCertInfo    ObjectType = 7
	OTServiceInfo ObjectType = 8
	OTRegistrar   ObjectType = 9
	OTRegistrant  ObjectType = 10
	OTInfraKey    ObjectType = 11
	OTExtraKey    ObjectType = 12
)

//SubjectAddr TODO correct?
type SubjectAddr struct {
	AddressFamily string
	PrefixLength  uint
	Address       string
}

//AddressAssertionSection contains information about the address assertion
type AddressAssertionSection struct {
	SubjectAddr
	Content    []Object
	Signatures []Signature
	Context    string
}

//AddressZoneSection contains information about the address zone
type AddressZoneSection struct {
	SubjectAddr
	Signatures []Signature
	Context    string
	Content    []AddressAssertionSection
}

//AddressQuerySection contains information about the address query
type AddressQuerySection struct {
	SubjectAddr
	Token   []byte
	Context string
	Types   []int
	Expires int
	//Optional
	Options []int
}

//NotificationSection contains information about the notification
type NotificationSection struct {
	//Mandatory
	Token Token
	Type  NotificationType
	//Optional
	Data string
}

type NotificationType int

const (
	Heartbeat          NotificationType = 100
	CapHashNotKnown    NotificationType = 399
	BadMessage         NotificationType = 400
	RcvInconsistentMsg NotificationType = 403
	NoAssertionsExist  NotificationType = 404
	MsgTooLarge        NotificationType = 413
	UnspecServerErr    NotificationType = 500
	ServerNotCapable   NotificationType = 501
	NoAssertionAvail   NotificationType = 504
)

//Signature on a Rains message or section
type Signature struct {
	KeySpace   KeySpaceID
	Algorithm  SignatureAlgorithmType
	ValidSince int64
	ValidUntil int64
	Data       interface{}
}

//KeySpaceID identifies a key space
type KeySpaceID int

const (
	RainsKeySpace KeySpaceID = 0
)

//AlgorithmType specifies an identifier an algorithm
//TODO CFE how do we want to distinguish SignatureAlgorithmType and HashAlgorithmType
type KeyAlgorithmType int

func (k KeyAlgorithmType) String() string {
	return strconv.Itoa(int(k))
}

//SignatureAlgorithmType specifies a signature algorithm type
type SignatureAlgorithmType int

const (
	Ed25519  SignatureAlgorithmType = 1
	Ed448    SignatureAlgorithmType = 2
	Ecdsa256 SignatureAlgorithmType = 3
	Ecdsa384 SignatureAlgorithmType = 4
)

//FIXME CFE are these types necessary???
//Ed25519PublicKey is a 32-byte bit string
type Ed25519PublicKey [32]byte

//Ed448PublicKey is a 57-byte bit string
type Ed448PublicKey [57]byte

type Ecdsa256PublicKey struct {
	//TODO to implement
}

type Ecdsa384PublicKey struct {
	//TODO to implement
}

//HashAlgorithmType specifies a hash algorithm type
type HashAlgorithmType int

const (
	NoHashAlgo HashAlgorithmType = 0
	Sha256     HashAlgorithmType = 1
	Sha384     HashAlgorithmType = 2
	Sha512     HashAlgorithmType = 3
)

//PublicKey contains information about a public key
type PublicKey struct {
	//TODO CFE remove type if not needed anywhere
	Type       SignatureAlgorithmType
	Key        interface{}
	ValidFrom  int64
	ValidUntil int64
}

//NamesetExpression  encodes a modified POSIX Extended Regular Expression format
type NamesetExpression string

//CertificateObject contains certificate information
type CertificateObject struct {
	Type     ProtocolType
	Usage    CertificateUsage
	HashAlgo HashAlgorithmType
	Data     []byte
}

type ProtocolType int

const (
	PTUnspecified ProtocolType = 0
	PTTLS         ProtocolType = 1
)

type CertificateUsage int

const (
	CUTrustAnchor CertificateUsage = 2
	CUEndEntity   CertificateUsage = 3
)

//ServiceInfo contains information how to access a named service
type ServiceInfo struct {
	Name     string
	Port     uint16
	Priority uint
}

//Object is a container for different values determined by the given type.
type Object struct {
	Type  ObjectType
	Value interface{}
}


Reduce default maximum trajectory playback speed

# Copyright 2016 - 2018  Ternaris.
# SPDX-License-Identifier: AGPL-3.0-only

@0xa1475499038e2711;

using import "/marv_nodes/types.capnp".Comment;
using import "/marv_nodes/types.capnp".File;
using import "/marv_nodes/types.capnp".GeoJson;
using import "/marv_pycapnp/types.capnp".Timedelta;
using import "/marv_pycapnp/types.capnp".Timestamp;
using import "/marv_pycapnp/types.capnp".TimelineEvent;

using Filesize = UInt64;
using RowId = UInt64;

enum Align {
  left @0;
  center @1;
  right @2;
}

enum Formatter {
  string @0;
  filesize @1;
  int @2;
  rellink @3;
  datetime @4;
  timedelta @5;
  link @6;
  route @7;
  distance @8;
  speed @9;
  acceleration @10;
}

struct Cell {
  union {
    void @0 :Void;
    text @1 :Text;
    bool @2 :Bool;
    uint64 @3 :UInt64;
    link @4 :Link;
    timedelta @5 :Timedelta;
    timestamp @6 :Timestamp;
    route @7 :Route;
  }
}

struct Link {
  href @0 :Text;
  target @1 :Text = "_blank";
  title @2 :Text;
  download @3 :Text;
}

struct Route {
  route @0 :Text;
  id @1 :Text;
  title @2 :Text;
}

struct Compare {
  sections @0 :List(Section);
  title @1 :Text;
  error @2 :Text;
}

struct Detail {
  sections @0 :List(Section);
  summary @1 :Section;
  title @2 :Text;
  error @3 :Text;
}

struct Section {
  title @0 :Text;
  widgets @1 :List(Widget);
}

struct Widget {
  title @0 :Text;
  union {
    void @1 :Void;
    custom @12 :Custom;
    dropdown @14 :Dropdown;
    gallery @2 :Gallery;
    image @3 :Image;
    keyval @4 :Keyval;
    link @13 :Link;
    mpld3 @5 :Text;  # marv-partial or json
    map @6 :Map;
    mapPartial @11 :Text;
    pre @7 :Pre;
    table @8 :Table;
    pointcloud @9 :Pointcloud;
    video @10 :Video;
    plotly @15: Text;  # marv-partial
    pdf @16 :Pdf;  # marv-partial
    eventlist @17 :Eventlist;
  }

  struct Custom {
    type @0 :Text;
    data @1 :Text;  # json
  }

  struct Gallery {
    images @0 :List(Image);
  }

  struct Image {
    src @0 :Text;
  }

  struct Keyval {
    items @0 :List(Item);

    struct Item {
      title @0 :Text;
      formatter @1 :Formatter;
      list @2 :Bool;
      cell @3 :Cell;
    }
  }

  struct Map {
    zoom @0 :Zoom;
    layers @1 :List(Layer);
    bgcolor @2 :List(UInt8) = [240, 240, 240, 255];  # rgba
    speed :group {
      min @3 :Float32 = 1.0;
      max @4 :Float32 = 100.0;
      default @5 :Float32 = 1.0;
    }

    struct Layer {
      title @0 :Text;
      color @1 :List(UInt8);
      transform @2 :List(Float32) = [1, 0, 0, 0,
                                     0, 1, 0, 0,
                                     0, 0, 1, 0,
                                     0, 0, 0, 1];
      union {
        geojson @3 :GeoJson;
        tiles @4 :List(Tile);
      }
    }

    struct Tile {
      title @0 :Text;
      url @1 :Text;
      attribution @2: Text;
      zoom @3 :Zoom;
      retina @4 :UInt8 = 1;
    }

    struct Zoom {
      min @0 :Int8;
      max @1 :Int8;
    }
  }

  struct Dropdown {
    widgets @0 :List(Widget);
  }

  struct Pre {
    text @0 :Text;
  }

  struct Table {
    actions @0 :List(Action);
    columns @1 :List(Column);
    rows @2 :List(Row);
    sortcolumn @3 :Int16;
    sortorder @4 :Sortorder;

    struct Action {
      name @0 :Text;
      title @1 :Text;
      method @2 :HTTPMethod;
      data @3 :Text;

      enum HTTPMethod {
        post @0;
        get @1;
      }
    }

    struct Column {
      title @0 :Text;
      align @1 :Align;
      formatter @2 :Formatter;
      list @3 :Bool;
      sortkey @4 :Text;
    }

    struct Row {
      id @0 :RowId;
      cells @1 :List(Cell);
    }

    enum Sortorder {
      ascending @0;
      descending @1;
    }
  }

  struct Pointcloud {
    uri @0 :Text;
    # TODO: rename to blob or stream or src like for image and video?
    size @1 :UInt64;
    # Bytesize of point cloud stream blob
    pointsize @2 :Float32;
    transform @3 :List(Float32) = [1, 0, 0, 0,
                                   0, 1, 0, 0,
                                   0, 0, 1, 0,
                                   0, 0, 0, 1];
    speed :group {
      min @4 :Float32 = 1.0;
      max @5 :Float32 = 1000.0;
      default @6 :Float32 = 1.0;
    }
    rangex @7 :List(Float32);
    rangey @8 :List(Float32);
    rangez @9 :List(Float32);
    ranged @10 :List(Float32);
    frameid @11 :Text;
  }

  struct Video {
    src @0 :Text;
  }

  struct Pdf {
    src @0 :Text;
  }

  struct Eventlist {
    subtype @0: Text;
    events @1 :List(TimelineEvent);
  }
}

# Copyright 2016 - 2018  Ternaris.
# SPDX-License-Identifier: AGPL-3.0-only

@0xa1475499038e2711;

using import "/marv_nodes/types.capnp".Comment;
using import "/marv_nodes/types.capnp".File;
using import "/marv_nodes/types.capnp".GeoJson;
using import "/marv_pycapnp/types.capnp".Timedelta;
using import "/marv_pycapnp/types.capnp".Timestamp;
using import "/marv_pycapnp/types.capnp".TimelineEvent;

using Filesize = UInt64;
using RowId = UInt64;

enum Align {
  left @0;
  center @1;
  right @2;
}

enum Formatter {
  string @0;
  filesize @1;
  int @2;
  rellink @3;
  datetime @4;
  timedelta @5;
  link @6;
  route @7;
  distance @8;
  speed @9;
  acceleration @10;
}

struct Cell {
  union {
    void @0 :Void;
    text @1 :Text;
    bool @2 :Bool;
    uint64 @3 :UInt64;
    link @4 :Link;
    timedelta @5 :Timedelta;
    timestamp @6 :Timestamp;
    route @7 :Route;
  }
}

struct Link {
  href @0 :Text;
  target @1 :Text = "_blank";
  title @2 :Text;
  download @3 :Text;
}

struct Route {
  route @0 :Text;
  id @1 :Text;
  title @2 :Text;
}

struct Compare {
  sections @0 :List(Section);
  title @1 :Text;
  error @2 :Text;
}

struct Detail {
  sections @0 :List(Section);
  summary @1 :Section;
  title @2 :Text;
  error @3 :Text;
}

struct Section {
  title @0 :Text;
  widgets @1 :List(Widget);
}

struct Widget {
  title @0 :Text;
  union {
    void @1 :Void;
    custom @12 :Custom;
    dropdown @14 :Dropdown;
    gallery @2 :Gallery;
    image @3 :Image;
    keyval @4 :Keyval;
    link @13 :Link;
    mpld3 @5 :Text;  # marv-partial or json
    map @6 :Map;
    mapPartial @11 :Text;
    pre @7 :Pre;
    table @8 :Table;
    pointcloud @9 :Pointcloud;
    video @10 :Video;
    plotly @15: Text;  # marv-partial
    pdf @16 :Pdf;  # marv-partial
    eventlist @17 :Eventlist;
  }

  struct Custom {
    type @0 :Text;
    data @1 :Text;  # json
  }

  struct Gallery {
    images @0 :List(Image);
  }

  struct Image {
    src @0 :Text;
  }

  struct Keyval {
    items @0 :List(Item);

    struct Item {
      title @0 :Text;
      formatter @1 :Formatter;
      list @2 :Bool;
      cell @3 :Cell;
    }
  }

  struct Map {
    zoom @0 :Zoom;
    layers @1 :List(Layer);
    bgcolor @2 :List(UInt8) = [240, 240, 240, 255];  # rgba
    speed :group {
      min @3 :Float32 = 1.0;
      max @4 :Float32 = 1000.0;
      default @5 :Float32 = 1.0;
    }

    struct Layer {
      title @0 :Text;
      color @1 :List(UInt8);
      transform @2 :List(Float32) = [1, 0, 0, 0,
                                     0, 1, 0, 0,
                                     0, 0, 1, 0,
                                     0, 0, 0, 1];
      union {
        geojson @3 :GeoJson;
        tiles @4 :List(Tile);
      }
    }

    struct Tile {
      title @0 :Text;
      url @1 :Text;
      attribution @2: Text;
      zoom @3 :Zoom;
      retina @4 :UInt8 = 1;
    }

    struct Zoom {
      min @0 :Int8;
      max @1 :Int8;
    }
  }

  struct Dropdown {
    widgets @0 :List(Widget);
  }

  struct Pre {
    text @0 :Text;
  }

  struct Table {
    actions @0 :List(Action);
    columns @1 :List(Column);
    rows @2 :List(Row);
    sortcolumn @3 :Int16;
    sortorder @4 :Sortorder;

    struct Action {
      name @0 :Text;
      title @1 :Text;
      method @2 :HTTPMethod;
      data @3 :Text;

      enum HTTPMethod {
        post @0;
        get @1;
      }
    }

    struct Column {
      title @0 :Text;
      align @1 :Align;
      formatter @2 :Formatter;
      list @3 :Bool;
      sortkey @4 :Text;
    }

    struct Row {
      id @0 :RowId;
      cells @1 :List(Cell);
    }

    enum Sortorder {
      ascending @0;
      descending @1;
    }
  }

  struct Pointcloud {
    uri @0 :Text;
    # TODO: rename to blob or stream or src like for image and video?
    size @1 :UInt64;
    # Bytesize of point cloud stream blob
    pointsize @2 :Float32;
    transform @3 :List(Float32) = [1, 0, 0, 0,
                                   0, 1, 0, 0,
                                   0, 0, 1, 0,
                                   0, 0, 0, 1];
    speed :group {
      min @4 :Float32 = 1.0;
      max @5 :Float32 = 1000.0;
      default @6 :Float32 = 1.0;
    }
    rangex @7 :List(Float32);
    rangey @8 :List(Float32);
    rangez @9 :List(Float32);
    ranged @10 :List(Float32);
    frameid @11 :Text;
  }

  struct Video {
    src @0 :Text;
  }

  struct Pdf {
    src @0 :Text;
  }

  struct Eventlist {
    subtype @0: Text;
    events @1 :List(TimelineEvent);
  }
}


catalog: make (User|Group)Ref.id default to -1

This allows a null ref to behave identically to a zero ref, at the small
(at the moment) expense of being a backward-incompatible schema change.
That's what pre-1.0 is for!

Updates #4

# Copyright 2016 The Minimal Configuration Manager Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

using Cxx = import "/third_party/capnproto/c++/src/capnp/c++.capnp";
using Go = import "/third_party/golang/capnproto/std/go.capnp";

@0x88881ae7af33bcb5;
$Cxx.namespace("mcm");
$Go.package("catalog");
$Go.import("github.com/zombiezen/mcm/catalog");

struct Catalog {
  # The root struct in a catalog file.

  resources @0 :List(Resource);
}

using ResourceId = UInt64;

struct Resource {
  id @0 :ResourceId $Go.name("ID");
  # The resource's identifier, used for dependencies.
  # The identifier should be unique within a catalog and cannot be zero.

  comment @1 :Text;
  # An optional human-readable description of the resource for use in
  # error and progress messages.

  dependencies @2 :List(ResourceId);
  # Resources that must be applied before this resource can be applied.

  union {
    noop @3 :Void;
    # Does nothing.  Mainly to give the resource a safe default.

    file @4 :File;
    exec @5 :Exec;
  }
}

struct File @0x8dc4ac52b2962163 {
  # An entry on the filesystem.

  path @0 :Text;
  # An absolute OS-specific file path.

  union {
    plain :group {
      content @1 :Data;
      # Byte content of the file.  If null, then file content is
      # untouched by the executor, but it is an error if the file does
      # not exist.

      mode @2 :Mode;
    }
    directory :group {
      mode @3 :Mode;
    }
    symlink :group {
      target @5 :Text;
      # Where the link should point to.  This may be an absolute path or
      # a path relative to the link.
    }

    absent @4 :Void;
  }

  struct Mode {
    const unset :UInt16 = 0xffff;
    const permMask :UInt16 = 0x01ff;
    const sticky :UInt16 = 0x0200;
    const setuid :UInt16 = 0x0400;
    const setgid :UInt16 = 0x0800;

    bits @2 :UInt16 = File.Mode.unset;
    # The Unix mode bits, specified in a system-independent manner using
    # the constants above.  If the field is the default value, then
    # don't change the mode.

    user @0 :UserRef;
    # OS owner of the file.  If null, then don't change.
    group @1 :GroupRef;
    # OS group of the file.  If null, then don't change.
  }
}

struct UserRef {
  # A reference to a OS user.

  union {
    id @0 :Int32 = -1 $Go.name("ID");
    name @1 :Text;
  }
}

struct GroupRef {
  # A reference to an OS group.

  union {
    id @0 :Int32 = -1 $Go.name("ID");
    name @1 :Text;
  }
}

struct Exec @0x984c97311006f1ca {
  # An execution of an arbitrary program.

  struct Command {
    # An individual program invocation.

    union {
      argv @0 :List(Text);
      # A list of arguments as passed to exec.
      # There must be at least one argument, which must be an absolute
      # path to the executable.

      bash @1 :Text;
      # A script as passed to bash.
    }

    struct EnvVar {
      # A single environment variable.

      name @0 :Text;
      value @1 :Text;
    }

    environment @2 :List(EnvVar);
    # The subprocess's environment.
    # An empty or null list is an empty environment.

    workingDirectory @3 :Text;
    # The subprocess's working directory.
    # An empty or null string is the root.
  }

  command @0 :Command;
  # Command to run if the condition is met.

  condition :union {
    always @1 :Void;
    # Command will always be run.  Used if the command is idempotent.
    onlyIf @2 :Command;
    # Command will be run only if another command returns a successful
    # exit code.  It is assumed that this command does not do anything
    # destructive and may be run multiple times.
    unless @3 :Command;
    # Command will be run only if another command returns a failure exit
    # code.  It is assumed that this command does not do anything
    # destructive and may be run multiple times.
    fileAbsent @4 :Text;
    # Command will be run only if the OS file path does not exist.
    ifDepsChanged @5 :List(ResourceId);
    # Command will be run only if one of the resources listed made a
    # change to the system during application.  It is an error for the
    # list to be empty or for the list to contain IDs that are not in
    # the resource's dependencies list.
  }
}

# Copyright 2016 The Minimal Configuration Manager Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

using Cxx = import "/third_party/capnproto/c++/src/capnp/c++.capnp";
using Go = import "/third_party/golang/capnproto/std/go.capnp";

@0x88881ae7af33bcb5;
$Cxx.namespace("mcm");
$Go.package("catalog");
$Go.import("github.com/zombiezen/mcm/catalog");

struct Catalog {
  # The root struct in a catalog file.

  resources @0 :List(Resource);
}

using ResourceId = UInt64;

struct Resource {
  id @0 :ResourceId $Go.name("ID");
  # The resource's identifier, used for dependencies.
  # The identifier should be unique within a catalog and cannot be zero.

  comment @1 :Text;
  # An optional human-readable description of the resource for use in
  # error and progress messages.

  dependencies @2 :List(ResourceId);
  # Resources that must be applied before this resource can be applied.

  union {
    noop @3 :Void;
    # Does nothing.  Mainly to give the resource a safe default.

    file @4 :File;
    exec @5 :Exec;
  }
}

struct File @0x8dc4ac52b2962163 {
  # An entry on the filesystem.

  path @0 :Text;
  # An absolute OS-specific file path.

  union {
    plain :group {
      content @1 :Data;
      # Byte content of the file.  If null, then file content is
      # untouched by the executor, but it is an error if the file does
      # not exist.

      mode @2 :Mode;
    }
    directory :group {
      mode @3 :Mode;
    }
    symlink :group {
      target @5 :Text;
      # Where the link should point to.  This may be an absolute path or
      # a path relative to the link.
    }

    absent @4 :Void;
  }

  struct Mode {
    const unset :UInt16 = 0xffff;
    const permMask :UInt16 = 0x01ff;
    const sticky :UInt16 = 0x0200;
    const setuid :UInt16 = 0x0400;
    const setgid :UInt16 = 0x0800;

    bits @2 :UInt16 = File.Mode.unset;
    # The Unix mode bits, specified in a system-independent manner using
    # the constants above.  If the field is the default value, then
    # don't change the mode.

    user @0 :UserRef;
    # OS owner of the file.  If null, then don't change.
    group @1 :GroupRef;
    # OS group of the file.  If null, then don't change.
  }
}

struct UserRef {
  # A reference to a OS user.

  union {
    id @0 :Int32;
    name @1 :Text;
  }
}

struct GroupRef {
  # A reference to an OS group.

  union {
    id @0 :Int32;
    name @1 :Text;
  }
}

struct Exec @0x984c97311006f1ca {
  # An execution of an arbitrary program.

  struct Command {
    # An individual program invocation.

    union {
      argv @0 :List(Text);
      # A list of arguments as passed to exec.
      # There must be at least one argument, which must be an absolute
      # path to the executable.

      bash @1 :Text;
      # A script as passed to bash.
    }

    struct EnvVar {
      # A single environment variable.

      name @0 :Text;
      value @1 :Text;
    }

    environment @2 :List(EnvVar);
    # The subprocess's environment.
    # An empty or null list is an empty environment.

    workingDirectory @3 :Text;
    # The subprocess's working directory.
    # An empty or null string is the root.
  }

  command @0 :Command;
  # Command to run if the condition is met.

  condition :union {
    always @1 :Void;
    # Command will always be run.  Used if the command is idempotent.
    onlyIf @2 :Command;
    # Command will be run only if another command returns a successful
    # exit code.  It is assumed that this command does not do anything
    # destructive and may be run multiple times.
    unless @3 :Command;
    # Command will be run only if another command returns a failure exit
    # code.  It is assumed that this command does not do anything
    # destructive and may be run multiple times.
    fileAbsent @4 :Text;
    # Command will be run only if the OS file path does not exist.
    ifDepsChanged @5 :List(ResourceId);
    # Command will be run only if one of the resources listed made a
    # change to the system during application.  It is an error for the
    # list to be empty or for the list to contain IDs that are not in
    # the resource's dependencies list.
  }
}


more detailed definition of player & ball; might need more adjustments later on

@0xc98f2d65bc9a57fc;

using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("robocup2Dsim::core");

using Field = import "field.capnp";
using Physics = import "/core/physics.capnp";

enum PlayerType
{
    outfield @0;
    goalie @1;
}

enum UniformNumber
{
    one @0;
    two @1;
    three @2;
    four @3;
    five @4;
    six @5;
    seven @6;
    eight @7;
    nine @8;
    ten @9;
    eleven @10;
}

struct PlayerId
{
    side @0 :Field.Side;
    uniform @1 :UniformNumber;
    type @2 :PlayerType;
}

struct Player
{
    id @0 :PlayerId;
    position @1 :Physics.Position;
    stamina @2 :Physics.KiloJoule;
    effort @3 :Physics.KiloJoule;
    bodyDirection @4 :Physics.Degree;
    headDirection @5 :Physics.Degree;
    velocity @6 :Physics.MilliMetrePerSecond;
}

enum ParticipantType
{
    player @0;
    coach @1;
    referee @2;
    trainer @3;
}

struct Ball
{
    position @0 :Physics.Position;
    direction @1 :Physics.Degree;
    velocity @2 :Physics.MilliMetrePerSecond;
}

@0xc98f2d65bc9a57fc;

using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("robocup2Dsim::core");

using Field = import "field.capnp";
using Physics = import "/core/physics.capnp";

enum PlayerType
{
    outfield @0;
    goalie @1;
}

enum UniformNumber
{
    one @0;
    two @1;
    three @2;
    four @3;
    five @4;
    six @5;
    seven @6;
    eight @7;
    nine @8;
    ten @9;
    eleven @10;
}

struct PlayerId
{
    side @0 :Field.Side;
    uniform @1 :UniformNumber;
    type @2 :PlayerType;
}

struct Player
{
    id @0 :PlayerId;
}

enum ParticipantType
{
    player @0;
    coach @1;
    referee @2;
    trainer @3;
}

struct Ball {}


Jack </3: current appVersion to 4 after having to release 0.2.2 (appVersion 3)

@0xc2cc325507512399;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "ztxnreej8a0pqn97ccfhuckswjkrmsaavn85n5sgzk30tv2k4y9h",

  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in your app package to tell Sandstorm
    # about your app.

    appTitle = (defaultText = "SandForms"),

    appVersion = 4,  # Increment this for every release.

    appMarketingVersion = (defaultText = "0.3.0"),
    # Human-readable representation of appVersion. Should match the way you
    # identify versions of your app in documentation and marketing.

    actions = [
      # Define your "new document" handlers here.
      ( title = (defaultText = "New Form"),
        command = .myCommand
        # The command to run when starting for the first time. (".myCommand"
        # is just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand,
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.
    metadata = (
      icons = (
        appGrid = (svg = embed "../graphics/appGrid.svg"),
        grain = (svg = embed "../graphics/grain.svg"),
        market = (svg = embed "../graphics/market.svg"),
      ),

      website = "https://github.com/sandforms/sandforms",
      codeUrl = "https://github.com/sandforms/sandforms",
      license = (openSource = apache2),
      categories = [office, productivity],

      author = (
        contactEmail = "sandforms@jacksingleton.com",
        pgpSignature = embed "pgp-signature",
      ),

      pgpKeyring = embed "pgp-keyring",

      description = (defaultText = embed "description.md"),
      shortDescription = (defaultText = "Form App"),

      screenshots = [
        (width = 448, height = 343, png = embed "screenshot.png")
      ],
    ),
  ),
  sourceMap = (
    # The following directories will be copied into your package.
    searchPath = [
      ( sourcePath = "/home/vagrant/bundle" ),
      ( sourcePath = "/opt/meteor-spk/meteor-spk.deps" )
    ]
  ),

  alwaysInclude = [ "." ],
  # This says that we always want to include all files from the source map.
  # (An alternative is to automatically detect dependencies by watching what
  # the app opens while running in dev mode. To see what that looks like,
  # run `spk init` without the -A option.)

  bridgeConfig = (viewInfo = (permissions = [(name = "owner")]))
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);

@0xc2cc325507512399;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "ztxnreej8a0pqn97ccfhuckswjkrmsaavn85n5sgzk30tv2k4y9h",

  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in your app package to tell Sandstorm
    # about your app.

    appTitle = (defaultText = "SandForms"),

    appVersion = 3,  # Increment this for every release.

    appMarketingVersion = (defaultText = "0.3.0"),
    # Human-readable representation of appVersion. Should match the way you
    # identify versions of your app in documentation and marketing.

    actions = [
      # Define your "new document" handlers here.
      ( title = (defaultText = "New Form"),
        command = .myCommand
        # The command to run when starting for the first time. (".myCommand"
        # is just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand,
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.
    metadata = (
      icons = (
        appGrid = (svg = embed "../graphics/appGrid.svg"),
        grain = (svg = embed "../graphics/grain.svg"),
        market = (svg = embed "../graphics/market.svg"),
      ),

      website = "https://github.com/sandforms/sandforms",
      codeUrl = "https://github.com/sandforms/sandforms",
      license = (openSource = apache2),
      categories = [office, productivity],

      author = (
        contactEmail = "sandforms@jacksingleton.com",
        pgpSignature = embed "pgp-signature",
      ),

      pgpKeyring = embed "pgp-keyring",

      description = (defaultText = embed "description.md"),
      shortDescription = (defaultText = "Form App"),

      screenshots = [
        (width = 448, height = 343, png = embed "screenshot.png")
      ],
    ),
  ),
  sourceMap = (
    # The following directories will be copied into your package.
    searchPath = [
      ( sourcePath = "/home/vagrant/bundle" ),
      ( sourcePath = "/opt/meteor-spk/meteor-spk.deps" )
    ]
  ),

  alwaysInclude = [ "." ],
  # This says that we always want to include all files from the source map.
  # (An alternative is to automatically detect dependencies by watching what
  # the app opens while running in dev mode. To see what that looks like,
  # run `spk init` without the -A option.)

  bridgeConfig = (viewInfo = (permissions = [(name = "owner")]))
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);


bump sandstorm appVersion

bump sandstorm appVersion

@0xbbbe049af795122e;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "vfnwptfn02ty21w715snyyczw0nqxkv3jvawcah10c6z7hj1hnu0",
  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in your app package to tell Sandstorm
    # about your app.

    appTitle = (defaultText = "Rocket.Chat"),

    appVersion = 2,  # Increment this for every release.

    appMarketingVersion = (defaultText = "0.7.2445"),
    # Human-readable representation of appVersion. Should match the way you
    # identify versions of your app in documentation and marketing.

    actions = [
      # Define your "new document" handlers here.
      ( title = (defaultText = "New Rocket.Chat"),
        command = .myCommand
        # The command to run when starting for the first time. (".myCommand"
        # is just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand,
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.

    metadata = (
      icons = (
        appGrid = (svg = embed "rocket.chat-128.svg"),
        grain = (svg = embed "rocket.chat-24.svg"),
        market = (svg = embed "rocket.chat-150.svg"),
      ),

      website = "https://rocket.chat",
      codeUrl = "https://github.com/RocketChat/Rocket.Chat",
      license = (openSource = mit),
      categories = [communications, productivity],

      author = (
        contactEmail = "team@rocket.chat",
        pgpSignature = embed "pgp-signature",
        upstreamAuthor = "Rocket.Chat",
      ),
      pgpKeyring = embed "pgp-keyring",

      description = (defaultText = embed "description.md"),
      shortDescription = (defaultText = "Chat app"),

      screenshots = [
        (width = 1203, height = 760, png = embed "screenshot.png")
      ],

      changeLog = (defaultText = embed "CHANGELOG.md"),
    ),

  ),

  sourceMap = (
    # The following directories will be copied into your package.
    searchPath = [
      ( sourcePath = "/home/vagrant/bundle" ),
      ( sourcePath = "/opt/meteor-spk/meteor-spk.deps" )
    ]
  ),

  alwaysInclude = [ "." ]
  # This says that we always want to include all files from the source map.
  # (An alternative is to automatically detect dependencies by watching what
  # the app opens while running in dev mode. To see what that looks like,
  # run `spk init` without the -A option.)
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
    (key = "SANDSTORM", value = "1")
  ]
);

@0xbbbe049af795122e;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "vfnwptfn02ty21w715snyyczw0nqxkv3jvawcah10c6z7hj1hnu0",
  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in your app package to tell Sandstorm
    # about your app.

    appTitle = (defaultText = "Rocket.Chat"),

    appVersion = 1,  # Increment this for every release.

    appMarketingVersion = (defaultText = "0.7.2445"),
    # Human-readable representation of appVersion. Should match the way you
    # identify versions of your app in documentation and marketing.

    actions = [
      # Define your "new document" handlers here.
      ( title = (defaultText = "New Rocket.Chat"),
        command = .myCommand
        # The command to run when starting for the first time. (".myCommand"
        # is just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand,
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.

    metadata = (
      icons = (
        appGrid = (svg = embed "rocket.chat-128.svg"),
        grain = (svg = embed "rocket.chat-24.svg"),
        market = (svg = embed "rocket.chat-150.svg"),
      ),

      website = "https://rocket.chat",
      codeUrl = "https://github.com/RocketChat/Rocket.Chat",
      license = (openSource = mit),
      categories = [communications, productivity],

      author = (
        contactEmail = "team@rocket.chat",
        pgpSignature = embed "pgp-signature",
        upstreamAuthor = "Rocket.Chat",
      ),
      pgpKeyring = embed "pgp-keyring",

      description = (defaultText = embed "description.md"),
      shortDescription = (defaultText = "Chat app"),

      screenshots = [
        (width = 1203, height = 760, png = embed "screenshot.png")
      ],

      changeLog = (defaultText = embed "CHANGELOG.md"),
    ),

  ),

  sourceMap = (
    # The following directories will be copied into your package.
    searchPath = [
      ( sourcePath = "/home/vagrant/bundle" ),
      ( sourcePath = "/opt/meteor-spk/meteor-spk.deps" )
    ]
  ),

  alwaysInclude = [ "." ]
  # This says that we always want to include all files from the source map.
  # (An alternative is to automatically detect dependencies by watching what
  # the app opens while running in dev mode. To see what that looks like,
  # run `spk init` without the -A option.)
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
    (key = "SANDSTORM", value = "1")
  ]
);


Bump appVersion

Bump appVersion

@0xbbbe049af795122e;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
	# The package definition. Note that the spk tool looks specifically for the
	# "pkgdef" constant.

	id = "vfnwptfn02ty21w715snyyczw0nqxkv3jvawcah10c6z7hj1hnu0",
	# Your app ID is actually its public key. The private key was placed in
	# your keyring. All updates must be signed with the same key.

	manifest = (
		# This manifest is included in your app package to tell Sandstorm
		# about your app.

		appTitle = (defaultText = "Rocket.Chat"),

		appVersion = 38,  # Increment this for every release.

		appMarketingVersion = (defaultText = "0.36.0"),
		# Human-readable representation of appVersion. Should match the way you
		# identify versions of your app in documentation and marketing.

		actions = [
			# Define your "new document" handlers here.
			( title = (defaultText = "New Rocket.Chat"),
				command = .myCommand
				# The command to run when starting for the first time. (".myCommand"
				# is just a constant defined at the bottom of the file.)
			)
		],

		continueCommand = .myCommand,
		# This is the command called to start your app back up after it has been
		# shut down for inactivity. Here we're using the same command as for
		# starting a new instance, but you could use different commands for each
		# case.

		metadata = (
			icons = (
				appGrid = (svg = embed "rocket.chat-128.svg"),
				grain = (svg = embed "rocket.chat-24.svg"),
				market = (svg = embed "rocket.chat-150.svg"),
			),

			website = "https://rocket.chat",
			codeUrl = "https://github.com/RocketChat/Rocket.Chat",
			license = (openSource = mit),
			categories = [communications, productivity, office, social, developerTools],

			author = (
				contactEmail = "team@rocket.chat",
				pgpSignature = embed "pgp-signature",
				upstreamAuthor = "Rocket.Chat",
			),
			pgpKeyring = embed "pgp-keyring",

			description = (defaultText = embed "description.md"),
			shortDescription = (defaultText = "Chat app"),

			screenshots = [
				(width = 1024, height = 696, png = embed "screenshot1.png"),
				(width = 1024, height = 696, png = embed "screenshot2.png"),
				(width = 1024, height = 696, png = embed "screenshot3.png"),
				(width = 1024, height = 696, png = embed "screenshot4.png")
			],

			changeLog = (defaultText = embed "CHANGELOG.md"),
		),

	),

	sourceMap = (
		# The following directories will be copied into your package.
		searchPath = [
			( sourcePath = "/home/vagrant/bundle" ),
			( sourcePath = "/opt/meteor-spk/meteor-spk.deps" )
		]
	),

	alwaysInclude = [ "." ],
	# This says that we always want to include all files from the source map.
	# (An alternative is to automatically detect dependencies by watching what
	# the app opens while running in dev mode. To see what that looks like,
	# run `spk init` without the -A option.)

  bridgeConfig = (
    viewInfo = (
      eventTypes = [
				(name = "message", verbPhrase = (defaultText = "message received")),
				(name = "privateMessage", verbPhrase = (defaultText = "private message received"), requiredPermission = (explicitList = void)),
			]
    ),

    saveIdentityCaps = true,
  ),
);

const myCommand :Spk.Manifest.Command = (
	# Here we define the command used to start up your server.
	argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
	environ = [
		# Note that this defines the *entire* environment seen by your app.
		(key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
		(key = "SANDSTORM", value = "1"),
		(key = "Statistics_reporting", value = "false"),
		(key = "Accounts_AllowUserAvatarChange", value = "false"),
		(key = "Accounts_AllowUserProfileChange", value = "false")
	]
);

@0xbbbe049af795122e;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
	# The package definition. Note that the spk tool looks specifically for the
	# "pkgdef" constant.

	id = "vfnwptfn02ty21w715snyyczw0nqxkv3jvawcah10c6z7hj1hnu0",
	# Your app ID is actually its public key. The private key was placed in
	# your keyring. All updates must be signed with the same key.

	manifest = (
		# This manifest is included in your app package to tell Sandstorm
		# about your app.

		appTitle = (defaultText = "Rocket.Chat"),

		appVersion = 36,  # Increment this for every release.

		appMarketingVersion = (defaultText = "0.36.0"),
		# Human-readable representation of appVersion. Should match the way you
		# identify versions of your app in documentation and marketing.

		actions = [
			# Define your "new document" handlers here.
			( title = (defaultText = "New Rocket.Chat"),
				command = .myCommand
				# The command to run when starting for the first time. (".myCommand"
				# is just a constant defined at the bottom of the file.)
			)
		],

		continueCommand = .myCommand,
		# This is the command called to start your app back up after it has been
		# shut down for inactivity. Here we're using the same command as for
		# starting a new instance, but you could use different commands for each
		# case.

		metadata = (
			icons = (
				appGrid = (svg = embed "rocket.chat-128.svg"),
				grain = (svg = embed "rocket.chat-24.svg"),
				market = (svg = embed "rocket.chat-150.svg"),
			),

			website = "https://rocket.chat",
			codeUrl = "https://github.com/RocketChat/Rocket.Chat",
			license = (openSource = mit),
			categories = [communications, productivity, office, social, developerTools],

			author = (
				contactEmail = "team@rocket.chat",
				pgpSignature = embed "pgp-signature",
				upstreamAuthor = "Rocket.Chat",
			),
			pgpKeyring = embed "pgp-keyring",

			description = (defaultText = embed "description.md"),
			shortDescription = (defaultText = "Chat app"),

			screenshots = [
				(width = 1024, height = 696, png = embed "screenshot1.png"),
				(width = 1024, height = 696, png = embed "screenshot2.png"),
				(width = 1024, height = 696, png = embed "screenshot3.png"),
				(width = 1024, height = 696, png = embed "screenshot4.png")
			],

			changeLog = (defaultText = embed "CHANGELOG.md"),
		),

	),

	sourceMap = (
		# The following directories will be copied into your package.
		searchPath = [
			( sourcePath = "/home/vagrant/bundle" ),
			( sourcePath = "/opt/meteor-spk/meteor-spk.deps" )
		]
	),

	alwaysInclude = [ "." ],
	# This says that we always want to include all files from the source map.
	# (An alternative is to automatically detect dependencies by watching what
	# the app opens while running in dev mode. To see what that looks like,
	# run `spk init` without the -A option.)

  bridgeConfig = (
    viewInfo = (
      eventTypes = [
				(name = "message", verbPhrase = (defaultText = "message received")),
				(name = "privateMessage", verbPhrase = (defaultText = "private message received"), requiredPermission = (explicitList = void)),
			]
    ),

    saveIdentityCaps = true,
  ),
);

const myCommand :Spk.Manifest.Command = (
	# Here we define the command used to start up your server.
	argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
	environ = [
		# Note that this defines the *entire* environment seen by your app.
		(key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
		(key = "SANDSTORM", value = "1"),
		(key = "Statistics_reporting", value = "false"),
		(key = "Accounts_AllowUserAvatarChange", value = "false"),
		(key = "Accounts_AllowUserProfileChange", value = "false")
	]
);


Bump version.

Bump version.

@0xaecd42915acc793f;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "aax9j672p6z8n7nyupzvj2nmumeqd4upa0f7mgu8gprwmy53x04h",
  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    appTitle = (defaultText = "WordPress"),
    appVersion = 5,
    appMarketingVersion = (defaultText = "2015.07.15--4.2.3-alpha"),

    actions = [
      ( title = (defaultText = "New WordPress Site"),
        command = .startCommand
      )
    ],

    continueCommand = .continueCommand
  ),

  sourceMap = (
    searchPath = [
      ( sourcePath = "."),  # Search this directory first.
      ( sourcePath = "/",    # Then search the system root directory.
        hidePaths = [ "home", "proc", "sys",
                      "etc/nsswitch.conf", "etc/localtime",
                      "etc/host.conf", "etc/resolv.conf"]
      )
    ]
  ),

  fileList = "sandstorm-files.list",

  alwaysInclude = ["wordpress-read-only", "read-only-plugins"],

  bridgeConfig = (
    viewInfo = (
      permissions = [(name = "admin", title = (defaultText = "admin"),
                      description = (defaultText = "allows administrative actions")),
                     (name = "editor", title = (defaultText = "editor"),
                      description = (defaultText = "allows publishing of posts of others")),
                     (name = "author", title = (defaultText = "author"),
                      description = (defaultText = "allows publishing of own posts")),
                     (name = "contributor", title = (defaultText = "contributor"),
                      description = (defaultText = "allows writing of posts")),
                     (name = "subscriber", title = (defaultText = "subscriber"),
                      description = (defaultText = "allows profile customization"))],
      roles = [(title = (defaultText = "admin"),
                permissions = [true, true, true, true, true],
                verbPhrase = (defaultText = "can do anything")),
               (title = (defaultText = "editor"),
                permissions = [false, true, true, true, true],
                verbPhrase = (defaultText = "can publish posts of others")),
               (title = (defaultText = "author"),
                permissions = [false, false, true, true, true],
                verbPhrase = (defaultText = "can publish own posts")),
               (title = (defaultText = "contributor"),
                permissions = [false, false, false, true, true],
                verbPhrase = (defaultText = "can write posts"),
                default = true),
                (title = (defaultText = "subscriber"),
                permissions = [false, false, false, false, true],
                verbPhrase = (defaultText = "can customize profile"))]
    )
  )
);

const startCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "10000", "--", "/start.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);

const continueCommand :Spk.Manifest.Command = (
  argv = ["/sandstorm-http-bridge", "10000", "--", "/continue.sh"],
  environ = [
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);

@0xaecd42915acc793f;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "aax9j672p6z8n7nyupzvj2nmumeqd4upa0f7mgu8gprwmy53x04h",
  # Your app ID is actually its public key. The private key was placed in
  # your keyring. All updates must be signed with the same key.

  manifest = (
    appTitle = (defaultText = "WordPress"),
    appVersion = 4,
    appMarketingVersion = (defaultText = "2015.06.28--4.2.3-alpha"),

    actions = [
      ( title = (defaultText = "New WordPress Site"),
        command = .startCommand
      )
    ],

    continueCommand = .continueCommand
  ),

  sourceMap = (
    searchPath = [
      ( sourcePath = "."),  # Search this directory first.
      ( sourcePath = "/",    # Then search the system root directory.
        hidePaths = [ "home", "proc", "sys",
                      "etc/nsswitch.conf", "etc/localtime",
                      "etc/host.conf", "etc/resolv.conf"]
      )
    ]
  ),

  fileList = "sandstorm-files.list",

  alwaysInclude = ["wordpress-read-only", "read-only-plugins"],

  bridgeConfig = (
    viewInfo = (
      permissions = [(name = "admin", title = (defaultText = "admin"),
                      description = (defaultText = "allows administrative actions")),
                     (name = "editor", title = (defaultText = "editor"),
                      description = (defaultText = "allows publishing of posts of others")),
                     (name = "author", title = (defaultText = "author"),
                      description = (defaultText = "allows publishing of own posts")),
                     (name = "contributor", title = (defaultText = "contributor"),
                      description = (defaultText = "allows writing of posts")),
                     (name = "subscriber", title = (defaultText = "subscriber"),
                      description = (defaultText = "allows profile customization"))],
      roles = [(title = (defaultText = "admin"),
                permissions = [true, true, true, true, true],
                verbPhrase = (defaultText = "can do anything")),
               (title = (defaultText = "editor"),
                permissions = [false, true, true, true, true],
                verbPhrase = (defaultText = "can publish posts of others")),
               (title = (defaultText = "author"),
                permissions = [false, false, true, true, true],
                verbPhrase = (defaultText = "can publish own posts")),
               (title = (defaultText = "contributor"),
                permissions = [false, false, false, true, true],
                verbPhrase = (defaultText = "can write posts"),
                default = true),
                (title = (defaultText = "subscriber"),
                permissions = [false, false, false, false, true],
                verbPhrase = (defaultText = "can customize profile"))]
    )
  )
);

const startCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "10000", "--", "/start.sh"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);

const continueCommand :Spk.Manifest.Command = (
  argv = ["/sandstorm-http-bridge", "10000", "--", "/continue.sh"],
  environ = [
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin")
  ]
);


Add SANDSTORM=1 to the environment under Sandstorm

We add the SANDSTORM=1 environment variable to sandstorm-pkgdef.capnp so that
accounts-sandstorm will ensure that it's the only loaded accounts package when
running under Sandstorm.

# Use use the meteor-spk tool to generate a sandstorm package (spk) from this
# meteor application source code. https://github.com/sandstorm-io/meteor-spk
@0xa5275bd3ad124e12;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "m86q05rdvj14yvn78ghaxynqz7u2svw6rnttptxx49g1785cdv1h",
  # The app ID is actually its public key. The private key was placed in your
  # keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in our app package to tell Sandstorm about our
    # app.

    appTitle = (defaultText = "Wekan"),
    # The name of the app as it is displayed to the user.

    appVersion = 12,
    # Increment this for every release.

    appMarketingVersion = (defaultText = "0.11.0-rc2"),
    # Human-readable presentation of the app version.

    minUpgradableAppVersion = 0,
    # The minimum version of the app which can be safely replaced by this app
    # package without data loss.  This might be non-zero if the app's data store
    # format changed drastically in the past and the app is no longer able to
    # read the old format.

    actions = [
      # Define your "new document" handlers here.
      (
        title = (defaultText = "New board"),
        command = .myCommand,
        # The command to run when starting for the first time. (".myCommand" is
        # just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand,
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.

    metadata = (
      icons = (
        appGrid = (svg = embed "meta/icons/wekan-128.svg"),
        grain = (svg = embed "meta/icons/wekan-24.svg"),
        market = (svg = embed "meta/icons/wekan-150.svg"),
      ),

      website = "https://wekan.io",
      codeUrl = "https://github.com/wekan/wekan",
      license = (openSource = mit),
      categories = [productivity, office],

      author = (
        contactEmail = "mquandalle@wekan.io",
        pgpSignature = embed "meta/mquandalle-pgp-sig",
      ),

      pgpKeyring = embed "meta/keyring",

      description = (defaultText = embed "meta/description.md"),

      shortDescription = (defaultText = "Kanban board"),

      screenshots = [
        (
          width = 512,
          height = 330,
          jpeg = embed "meta/screenshots/board-view.jpg"
        ),
        # XXX The screenshots should have a standard width and height.
      ],

      changeLog = (
        defaultText = embed "CHANGELOG.md",
        localizations = [
          (locale = "fr", text = embed "meta/t9n-changelog/fr.md"),
        ],
      )
    )
  ),

  sourceMap = (
    # The following directories will be copied into your package.
    searchPath = [
      (sourcePath = ".meteor-spk/deps"),
      (sourcePath = ".meteor-spk/bundle"),
    ]
  ),

  alwaysInclude = [ "." ],
  # This says that we always want to include all files from the source map. (An
  # alternative is to automatically detect dependencies by watching what the app
  # opens while running in dev mode. To see what that looks like, run `spk init`
  # without the -A option.)

  bridgeConfig = (
    viewInfo = (
      permissions = [(
        name = "participate",
        title = (
          defaultText = "participate",
          localizations = [
            (locale = "fr", text = "participer"),
          ],
        ),
        description = (
          defaultText = "allows participating in the board",
          localizations = [
            (locale = "fr", text = "permet de participer dans le tableau"),
          ],
        )
      ), (
        name = "configure",
        title = (
          defaultText = "configure",
          localizations = [
            (locale = "fr", text = "configurer"),
          ],
        ),
        description = (
          defaultText = "allows configuring the board",
          localizations = [
            (locale = "fr", text = "permet de configurer le tableau"),
          ],
        )
      )],

      roles = [(
        title = (
          defaultText = "observer",
          localizations = [
            (locale = "fr", text = "observateur"),
          ],
        ),
        permissions = [false, false],
        verbPhrase = (
          defaultText = "can read",
          localizations = [
            (locale = "fr", text = "peut lire"),
          ],
        )
      ), (
        title = (
          defaultText = "member",
          localizations = [
            (locale = "fr", text = "membre"),
          ],
        ),
        permissions = [true, false],
        verbPhrase = (
          defaultText = "can edit",
          localizations = [
            (locale = "fr", text = "peut éditer"),
          ],
        ),
        default = true,
      # ), (
      #   title = (defaultText = "administrator"),
      #   permissions = [true, true],
      #   verbPhrase = (defaultText = "can configure")
      #
      # XXX Administrators configuration options aren’t implemented yet, so this
      # role is currently useless.
      )]
    )
  ),
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "4000", "--", "node", "start.js"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
    (key = "SANDSTORM", value = "1"),
    (key = "METEOR_SETTINGS", value = "{\"public\": {\"sandstorm\": true}}")
  ]
);

# Use use the meteor-spk tool to generate a sandstorm package (spk) from this
# meteor application source code. https://github.com/sandstorm-io/meteor-spk
@0xa5275bd3ad124e12;

using Spk = import "/sandstorm/package.capnp";
# This imports:
#   $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "m86q05rdvj14yvn78ghaxynqz7u2svw6rnttptxx49g1785cdv1h",
  # The app ID is actually its public key. The private key was placed in your
  # keyring. All updates must be signed with the same key.

  manifest = (
    # This manifest is included in our app package to tell Sandstorm about our
    # app.

    appTitle = (defaultText = "Wekan"),
    # The name of the app as it is displayed to the user.

    appVersion = 12,
    # Increment this for every release.

    appMarketingVersion = (defaultText = "0.11.0-rc2"),
    # Human-readable presentation of the app version.

    minUpgradableAppVersion = 0,
    # The minimum version of the app which can be safely replaced by this app
    # package without data loss.  This might be non-zero if the app's data store
    # format changed drastically in the past and the app is no longer able to
    # read the old format.

    actions = [
      # Define your "new document" handlers here.
      (
        title = (defaultText = "New board"),
        command = .myCommand,
        # The command to run when starting for the first time. (".myCommand" is
        # just a constant defined at the bottom of the file.)
      )
    ],

    continueCommand = .myCommand,
    # This is the command called to start your app back up after it has been
    # shut down for inactivity. Here we're using the same command as for
    # starting a new instance, but you could use different commands for each
    # case.

    metadata = (
      icons = (
        appGrid = (svg = embed "meta/icons/wekan-128.svg"),
        grain = (svg = embed "meta/icons/wekan-24.svg"),
        market = (svg = embed "meta/icons/wekan-150.svg"),
      ),

      website = "https://wekan.io",
      codeUrl = "https://github.com/wekan/wekan",
      license = (openSource = mit),
      categories = [productivity, office],

      author = (
        contactEmail = "mquandalle@wekan.io",
        pgpSignature = embed "meta/mquandalle-pgp-sig",
      ),

      pgpKeyring = embed "meta/keyring",

      description = (defaultText = embed "meta/description.md"),

      shortDescription = (defaultText = "Kanban board"),

      screenshots = [
        (
          width = 512,
          height = 330,
          jpeg = embed "meta/screenshots/board-view.jpg"
        ),
        # XXX The screenshots should have a standard width and height.
      ],

      changeLog = (
        defaultText = embed "CHANGELOG.md",
        localizations = [
          (locale = "fr", text = embed "meta/t9n-changelog/fr.md"),
        ],
      )
    )
  ),

  sourceMap = (
    # The following directories will be copied into your package.
    searchPath = [
      (sourcePath = ".meteor-spk/deps"),
      (sourcePath = ".meteor-spk/bundle"),
    ]
  ),

  alwaysInclude = [ "." ],
  # This says that we always want to include all files from the source map. (An
  # alternative is to automatically detect dependencies by watching what the app
  # opens while running in dev mode. To see what that looks like, run `spk init`
  # without the -A option.)

  bridgeConfig = (
    viewInfo = (
      permissions = [(
        name = "participate",
        title = (
          defaultText = "participate",
          localizations = [
            (locale = "fr", text = "participer"),
          ],
        ),
        description = (
          defaultText = "allows participating in the board",
          localizations = [
            (locale = "fr", text = "permet de participer dans le tableau"),
          ],
        )
      ), (
        name = "configure",
        title = (
          defaultText = "configure",
          localizations = [
            (locale = "fr", text = "configurer"),
          ],
        ),
        description = (
          defaultText = "allows configuring the board",
          localizations = [
            (locale = "fr", text = "permet de configurer le tableau"),
          ],
        )
      )],

      roles = [(
        title = (
          defaultText = "observer",
          localizations = [
            (locale = "fr", text = "observateur"),
          ],
        ),
        permissions = [false, false],
        verbPhrase = (
          defaultText = "can read",
          localizations = [
            (locale = "fr", text = "peut lire"),
          ],
        )
      ), (
        title = (
          defaultText = "member",
          localizations = [
            (locale = "fr", text = "membre"),
          ],
        ),
        permissions = [true, false],
        verbPhrase = (
          defaultText = "can edit",
          localizations = [
            (locale = "fr", text = "peut éditer"),
          ],
        ),
        default = true,
      # ), (
      #   title = (defaultText = "administrator"),
      #   permissions = [true, true],
      #   verbPhrase = (defaultText = "can configure")
      #
      # XXX Administrators configuration options aren’t implemented yet, so this
      # role is currently useless.
      )]
    )
  ),
);

const myCommand :Spk.Manifest.Command = (
  # Here we define the command used to start up your server.
  argv = ["/sandstorm-http-bridge", "4000", "--", "node", "start.js"],
  environ = [
    # Note that this defines the *entire* environment seen by your app.
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
    (key = "METEOR_SETTINGS", value = "{\"public\": {\"sandstorm\": true}}")
  ]
);


adding spec for new api calls

adding spec for new api calls


.sandstorm: rename app to Sandpass

.sandstorm: rename app to Sandpass

@0xba54be93d5898b97;

using Spk = import "/sandstorm/package.capnp";

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "rq41p170hcs5rzg66axggv8r90fjcssdky8891kq5s7jcpm1813h",
  manifest = (
    appTitle = (defaultText = "Sandpass"),
    appVersion = 0,  # Increment this for every release.
    appMarketingVersion = (defaultText = "0.1.0"),

    actions = [
      ( nounPhrase = (defaultText = "database"),
        command = .launcher
      )
    ],
    continueCommand = .launcher,

    metadata = (
      icons = (
        # Various icons to represent the app in various contexts.
        #appGrid = (svg = embed "path/to/appgrid-128x128.svg"),
        #grain = (svg = embed "path/to/grain-24x24.svg"),
        #market = (svg = embed "path/to/market-150x150.svg"),
        #marketBig = (svg = embed "path/to/market-big-300x300.svg"),
      ),

      website = "https://github.com/zombiezen/sandpass",
      codeUrl = "https://github.com/zombiezen/sandpass",

      license = (openSource = apache2,
                 notices = (defaultText = embed "notices.txt")),

      categories = [productivity],

      author = (
        contactEmail = "ross@zombiezen.com",

        pgpSignature = embed "pgp-signature",
      ),

      pgpKeyring = embed "pgp-keyring",

      #description = (defaultText = embed "path/to/description.md"),
      # The app's description in Github-flavored Markdown format, to be displayed e.g.
      # in an app store. Note that the Markdown is not permitted to contain HTML nor image tags (but
      # you can include a list of screenshots separately).

      shortDescription = (defaultText = "Password manager"),

      screenshots = [
        # Screenshots to use for marketing purposes.  Examples below.
        # Sizes are given in device-independent pixels, so if you took these
        # screenshots on a Retina-style high DPI screen, divide each dimension by two.

        #(width = 746, height = 795, jpeg = embed "path/to/screenshot-1.jpeg"),
        #(width = 640, height = 480, png = embed "path/to/screenshot-2.png"),
      ],
      #changeLog = (defaultText = embed "path/to/sandstorm-specific/changelog.md"),
      # Documents the history of changes in Github-flavored markdown format (with the same restrictions
      # as govern `description`). We recommend formatting this with an H1 heading for each version
      # followed by a bullet list of changes.
    ),
  ),

  sourceMap = (
    searchPath = [
      ( sourcePath = "." ),  # Search this directory first.
      ( sourcePath = "/",    # Then search the system root directory.
        hidePaths = [ "home", "proc", "sys",
                      "etc/passwd", "etc/hosts", "etc/host.conf",
                      "etc/nsswitch.conf", "etc/resolv.conf",
                      "etc/ld.so.cache" ]
      )
    ]
  ),

  fileList = "sandstorm-files.list",

  alwaysInclude = [
    "opt/app/sandpass",
    "opt/app/templates",
  ],

  bridgeConfig = (
    viewInfo = (
      permissions = [
        ( name = "read",
          title = (defaultText = "Read from database")
        ),
        ( name = "write",
          title = (defaultText = "Write to database")
        )
      ],
      roles = [
        ( title = (defaultText = "viewer"),
          verbPhrase = (defaultText = "can read"),
          permissions = [true, false]
        ),
        ( title = (defaultText = "editor"),
          verbPhrase = (defaultText = "can read and write"),
          permissions = [true, true]
        )
      ]
    )
  )
);

const launcher :Spk.Manifest.Command = (
  argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
  environ = [
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
    (key = "SANDSTORM", value = "1"),
  ]
);

@0xba54be93d5898b97;

using Spk = import "/sandstorm/package.capnp";

const pkgdef :Spk.PackageDefinition = (
  # The package definition. Note that the spk tool looks specifically for the
  # "pkgdef" constant.

  id = "rq41p170hcs5rzg66axggv8r90fjcssdky8891kq5s7jcpm1813h",
  manifest = (
    appTitle = (defaultText = "KeePass"),
    appVersion = 0,  # Increment this for every release.
    appMarketingVersion = (defaultText = "0.1.0"),

    actions = [
      ( nounPhrase = (defaultText = "database"),
        command = .launcher
      )
    ],
    continueCommand = .launcher,

    metadata = (
      icons = (
        # Various icons to represent the app in various contexts.
        #appGrid = (svg = embed "path/to/appgrid-128x128.svg"),
        #grain = (svg = embed "path/to/grain-24x24.svg"),
        #market = (svg = embed "path/to/market-150x150.svg"),
        #marketBig = (svg = embed "path/to/market-big-300x300.svg"),
      ),

      website = "https://github.com/zombiezen/sandpass",
      codeUrl = "https://github.com/zombiezen/sandpass",

      license = (openSource = apache2,
                 notices = (defaultText = embed "notices.txt")),

      categories = [productivity],

      author = (
        contactEmail = "ross@zombiezen.com",

        pgpSignature = embed "pgp-signature",
      ),

      pgpKeyring = embed "pgp-keyring",

      #description = (defaultText = embed "path/to/description.md"),
      # The app's description in Github-flavored Markdown format, to be displayed e.g.
      # in an app store. Note that the Markdown is not permitted to contain HTML nor image tags (but
      # you can include a list of screenshots separately).

      shortDescription = (defaultText = "Password manager"),

      screenshots = [
        # Screenshots to use for marketing purposes.  Examples below.
        # Sizes are given in device-independent pixels, so if you took these
        # screenshots on a Retina-style high DPI screen, divide each dimension by two.

        #(width = 746, height = 795, jpeg = embed "path/to/screenshot-1.jpeg"),
        #(width = 640, height = 480, png = embed "path/to/screenshot-2.png"),
      ],
      #changeLog = (defaultText = embed "path/to/sandstorm-specific/changelog.md"),
      # Documents the history of changes in Github-flavored markdown format (with the same restrictions
      # as govern `description`). We recommend formatting this with an H1 heading for each version
      # followed by a bullet list of changes.
    ),
  ),

  sourceMap = (
    searchPath = [
      ( sourcePath = "." ),  # Search this directory first.
      ( sourcePath = "/",    # Then search the system root directory.
        hidePaths = [ "home", "proc", "sys",
                      "etc/passwd", "etc/hosts", "etc/host.conf",
                      "etc/nsswitch.conf", "etc/resolv.conf",
                      "etc/ld.so.cache" ]
      )
    ]
  ),

  fileList = "sandstorm-files.list",

  alwaysInclude = [
    "opt/app/sandpass",
    "opt/app/templates",
  ],

  bridgeConfig = (
    viewInfo = (
      permissions = [
        ( name = "read",
          title = (defaultText = "Read from database")
        ),
        ( name = "write",
          title = (defaultText = "Write to database")
        )
      ],
      roles = [
        ( title = (defaultText = "viewer"),
          verbPhrase = (defaultText = "can read"),
          permissions = [true, false]
        ),
        ( title = (defaultText = "editor"),
          verbPhrase = (defaultText = "can read and write"),
          permissions = [true, true]
        )
      ]
    )
  )
);

const launcher :Spk.Manifest.Command = (
  argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"],
  environ = [
    (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
    (key = "SANDSTORM", value = "1"),
  ]
);