Documentation
¶
Index ¶
- Constants
- Variables
- func ArtifactMediaType(path string) string
- func Dispatch(ctx context.Context, h Handler, action string, args map[string]any) (any, error)
- func Expiry(preset string) (pgtype.Timestamptz, error)
- func InputSchema() map[string]any
- func NewToken() (string, string, error)
- func OpenSafeRoot(root, rel string) (*os.Root, string, error)
- func RenderMarkdownPage(opts RenderMarkdownOpts, markdown []byte) ([]byte, error)
- func SafePath(root, rel string) (string, error)
- func TokenHash(token string) string
- func WorkspaceRootForScope(stellaHome, userID, agentID, scope string) string
- type Access
- func (a *Access) List(ctx context.Context, limit, offset int) (ListResult, error)
- func (a *Access) Revoke(ctx context.Context, id string) error
- func (a *Access) ShareArticle(ctx context.Context, articleID, expiresIn string) (Created, error)
- func (a *Access) ShareArtifact(ctx context.Context, ...) (Created, error)
- type ArticleInput
- type ArtifactInput
- type Created
- type Handler
- type ListInput
- type ListResult
- type RenderMarkdownOpts
- type RevokeInput
- type Service
- type Share
- type Tool
Constants ¶
const InputSchemaJSON = `` /* 2853-byte string literal not displayed */
const ToolName = "share"
Variables ¶
var ( ErrPathEscapes = errors.New("path escapes workspace root") ErrTooLarge = errors.New("file is too large to share") ErrUnsupportedType = errors.New("unsupported artifact type") ErrDirectory = errors.New("path is a directory") ErrNoContent = errors.New("article has no content") ErrInvalidInput = errors.New("invalid input") )
Functions ¶
func ArtifactMediaType ¶
func InputSchema ¶
func OpenSafeRoot ¶
OpenSafeRoot returns an os.Root and root-relative name. Security-sensitive operations use Root methods so symlink swaps cannot escape the workspace.
func RenderMarkdownPage ¶
func RenderMarkdownPage(opts RenderMarkdownOpts, markdown []byte) ([]byte, error)
func WorkspaceRootForScope ¶
Types ¶
type Access ¶
type Access struct {
// contains filtered or unexported fields
}
Access is one share use case bound to one trusted Authority. A share is a user-owned capability: ownership is the captured userID, and every durable query is scoped to it. agentScoped/agentID record the actor so an AgentActor (agent tool) is confined to its bound agent's workspace, while a UserActor (HTTP) selects the workspace agent from the request body, not from identity. There is no policy evaluation; the acting user (and, for artifacts, the os.Root-confined workspace) is the boundary. The public capability-URL view (token hash + expiry, no session) is served outside Access entirely.
func (*Access) List ¶
List returns the acting user's own shares. The query is scoped to the captured userID, so it can never surface another user's shares.
func (*Access) Revoke ¶
Revoke disables one of the acting user's shares. The delete is scoped to the captured userID, so a share owned by another user is never touched; a missing (or foreign) row is ErrNotFound.
func (*Access) ShareArticle ¶
ShareArticle publishes a rendered Recally article owned by the acting user.
func (*Access) ShareArtifact ¶
func (a *Access) ShareArtifact(ctx context.Context, sessionID, path, scope, requestedAgentID, expiresIn string) (Created, error)
ShareArtifact publishes a workspace file for the acting user. requestedAgentID selects which session/workspace to read: for a UserActor it is the request-body agent id (a resource selector, not identity); for an agent-scoped AgentActor it must equal the bound agent, so a delegated turn can never reach another agent's workspace. The UserID/AgentID/AgentScoped semantics passed to sessionWorkspaceRoot preserve the workspace confinement exactly.
type ArticleInput ¶
type ArtifactInput ¶
type ListResult ¶
type ListResult struct {
NextPageToken string
}
type RenderMarkdownOpts ¶
type RevokeInput ¶
type RevokeInput struct {
Id string `json:"id,omitempty"`
}
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
func NewService ¶
func NewServiceForPool ¶
func NewServiceForPool(pool *pgxpool.Pool, mem memory.Provider, store *recally.Store, assets *asset.Store, stellaHome, baseURL string) *Service
NewServiceForPool creates a share service that owns the sqlc query set for the share tables, so callers pass only the pgx pool.
func (*Service) Access ¶
Access binds one share use case to a trusted Authority. It rejects an invalid Authority (403) and one carrying no user (401) up front, so every method can assume a non-empty acting user.
func (*Service) PublicContent ¶
PublicContent resolves a public share by its capability token. It hashes the token, looks the row up by hash, and returns the share with its content. This is the capability-URL view served without a session (see Access), so it does not authorize against a user; possession of the unguessable token is the grant. An unknown token (or any lookup failure) is authz.ErrNotFound, so the transport surfaces a uniform 404 and never distinguishes missing from expired.
type Share ¶
type Share struct {
}
Share is the transport-neutral view of one share row. Content carries the stored bytes for a freshly created share and the public token view; it is nil for list summaries, whose query does not select the payload. Times are UTC; ExpiresAt is nil for a share that never expires. This is the only share shape that crosses the package boundary — callers never see sqlc rows or pgtype nulls.