// Package server provides a server which keeps a principal in memory
// and allows clients to use that principal.
//
// PROTOCOL
//
// The agent starts processes with the VEYRON_AGENT_FD set to one end of a
// unix domain socket. To connect to the agent, a client should create
// a unix domain socket pair. Then send one end of the socket to the agent
// with 1 byte of data. The agent will then serve the Agent service on
// the recieved socket, using VCSecurityNone.
//
// The agent also supports an optional mode where it can manage multiple principals.
// Typically this is only used by Device Manager. In this mode, VEYRON_AGENT_FD
// will be 3, and there will be another socket at fd 4.
// Creating a new principal is similar to connecting to to agent: create a socket
// pair and send one end on fd 4 with 1 byte of data.
// Set the data to 1 to request the principal only be stored in memory.
// The agent will create a new principal and respond with a principal handle on fd 4.
// To connect using a previously created principal, create a socket pair and send
// one end with the principal handle as data on fd 4. The agent will not send a
// response on fd 4.
// In either, you can use the normal process to connect to an agent over the
// other end of the pair. Typically you would pass the other end to a child
// process and set VEYRON_AGENT_FD so it knows to connect.
//
// The protocol also has limited support for caching: A client can
// request notification when any other client modifies the principal so it
// can flush the cache. See NotifyWhenChanged for details.


package server

import (
	"v.io/v23/security"
)

type Agent interface {
	Bless(key []byte, wit security.WireBlessings, extension string, caveat security.Caveat, additionalCaveats []security.Caveat) (security.WireBlessings | error)
	BlessSelf(name string, caveats []security.Caveat) (security.WireBlessings | error)
	Sign(message []byte) (security.Signature | error)
	MintDischarge(forCaveat, caveatOnDischarge security.Caveat, additionalCaveatsOnDischarge []security.Caveat) (security.WireDischarge | error)
	PublicKey() ([]byte | error)
	BlessingsByName(name security.BlessingPattern) ([]security.WireBlessings | error)
	BlessingsInfo(blessings security.WireBlessings) (map[string][]security.Caveat | error)
	AddToRoots(blessing security.WireBlessings) error

	BlessingStoreSet(blessings security.WireBlessings, forPeers security.BlessingPattern) (security.WireBlessings | error)
	BlessingStoreForPeer(peerBlessings []string) (security.WireBlessings | error)
	BlessingStoreSetDefault(blessings security.WireBlessings) error
	BlessingStoreDefault() (security.WireBlessings | error)
	BlessingStorePeerBlessings() (map[security.BlessingPattern]security.WireBlessings | error)
	BlessingStoreDebugString() (string | error)

	BlessingRootsAdd(root []byte, pattern security.BlessingPattern) error
	BlessingRootsRecognized(root []byte, blessing string) error
	BlessingRootsDebugString() (string | error)

	// Clients using caching should call NotifyWhenChanged upon connecting to
	// the server. The server will stream back values whenever the client should
	// flush the cache. The streamed value is arbitrary, simply flush whenever
	// recieving a new item.
	NotifyWhenChanged() stream<_, bool> error
}
