Why: PR #209 is behind main by 14 commits (admin passwords, managed
interpreter path, U8 SQLite instance guard, EXT-20 regulations) and conflicted
in app wiring, host capabilities, migrations and the extension surface; the
user authorized merging the renderer line on 2026-10-18.
Evidence: content is the agent-exec transport 87a99ece (cursor worker, unit
backend-task10-sync-main-56a7f9f-r2, receipt
/tmp/cleanup-20261018/render/backend-sync-run2.json, SELF): gofmt, go build,
go vet and go test ./... (43 packages) passed. Host check: main migrations
1-36 unchanged, feature migrations moved from 36-47 to 37-48 in order with
identical SQL, surface.txt is the sorted union.
Impact: main's migration 36 instance_guard stays authoritative; databases that
ran unmerged feature builds with the old numbering must be recreated.
SurfaceVersion becomes 2.24.0-experimental.
Refs: PR #209, Backend main 56a7f9f
Co-authored-by: Cursor <cursoragent@cursor.com>
94 lines
3.8 KiB
Go
94 lines
3.8 KiB
Go
package extension
|
|
|
|
import "context"
|
|
|
|
const AccountDirectorySchemaVersion = 1
|
|
|
|
const (
|
|
AccountDirectoryPurposeSystemUsers = "system.users"
|
|
AccountDirectoryPurposeProjectMembers = "project.member-candidate"
|
|
AccountDirectoryPurposeDocumentDuties = "document.duty-candidate"
|
|
AccountDirectoryModeExact = "exact"
|
|
AccountDirectoryModeFuzzy = "fuzzy"
|
|
)
|
|
|
|
// AccountDirectoryQuery is a request for account candidates. Actor and field
|
|
// permissions are deliberately absent: the host supplies the authenticated
|
|
// dispatch actor and obtains current domain authorization from its registrar.
|
|
type AccountDirectoryQuery struct {
|
|
SchemaVersion int `json:"schemaVersion"`
|
|
Purpose string `json:"purpose"`
|
|
ProjectID string `json:"projectId,omitempty"`
|
|
DocumentID string `json:"documentId,omitempty"`
|
|
Mode string `json:"mode"`
|
|
Query string `json:"query"`
|
|
SearchFields []string `json:"searchFields,omitempty"`
|
|
Status string `json:"status,omitempty"` // enabled|disabled|all; domain candidates require enabled
|
|
Cursor string `json:"cursor,omitempty"`
|
|
Limit int `json:"limit,omitempty"`
|
|
}
|
|
|
|
// AccountDirectoryEntry contains only identity, effective state and fields
|
|
// specifically authorized for the current purpose. Contact details never use
|
|
// this candidate DTO.
|
|
type AccountDirectoryEntry struct {
|
|
UserID string `json:"userId"`
|
|
Owner string `json:"owner"`
|
|
Name string `json:"name,omitempty"`
|
|
StaffNo string `json:"staffNo,omitempty"`
|
|
Valid bool `json:"valid"`
|
|
}
|
|
|
|
type AccountDirectoryPage struct {
|
|
Entries []AccountDirectoryEntry `json:"entries"`
|
|
DirectoryVersion string `json:"directoryVersion"`
|
|
NextCursor string `json:"nextCursor,omitempty"`
|
|
}
|
|
|
|
type AccountDirectoryLookup struct {
|
|
Entry AccountDirectoryEntry `json:"entry"`
|
|
DirectoryVersion string `json:"directoryVersion"`
|
|
}
|
|
|
|
// AccountDirectoryProvider is optional on trusted dispatch Host handles.
|
|
// Missing capability is a denial, not permission to use EXT-19 as a fallback.
|
|
type AccountDirectoryProvider interface {
|
|
QueryAccountDirectory(context.Context, AccountDirectoryQuery) (AccountDirectoryPage, error)
|
|
LookupAccountDirectory(context.Context, AccountDirectoryQuery, string) (AccountDirectoryLookup, error)
|
|
// LookupAccountDirectoryOwner is an explicit legacy-owner compatibility
|
|
// lookup; it resolves to the same stable user ID and applies the same scope.
|
|
LookupAccountDirectoryOwner(context.Context, AccountDirectoryQuery, string) (AccountDirectoryLookup, error)
|
|
}
|
|
|
|
// AccountDirectoryScopeRequest is constructed by the Backend from the trusted
|
|
// dispatch actor, registered plugin and untrusted locator. A resolver must
|
|
// validate the locator and current member.manage / duty.assign authority.
|
|
type AccountDirectoryScopeRequest struct {
|
|
Actor string
|
|
PluginID string
|
|
Purpose string
|
|
ProjectID string
|
|
DocumentID string
|
|
}
|
|
|
|
// AccountDirectoryScope is returned by the trusted in-process domain resolver.
|
|
// AllCandidates is explicit: a nil candidate list never means global access.
|
|
// CandidateIDs or CandidateOwners are applied before search and pagination;
|
|
// domain membership stores may use owners while the provider returns stable IDs.
|
|
type AccountDirectoryScope struct {
|
|
AllowedFields []string
|
|
MatchFields []string
|
|
AllCandidates bool
|
|
CandidateIDs []string
|
|
CandidateOwners []string
|
|
ScopeVersion string
|
|
}
|
|
|
|
type AccountDirectoryScopeResolver func(context.Context, AccountDirectoryScopeRequest) (AccountDirectoryScope, error)
|
|
|
|
// AccountDirectoryRegistrar is optional on a compiled in-process Registry.
|
|
// Only the trusted RDM plugin may register the domain authorization resolver.
|
|
type AccountDirectoryRegistrar interface {
|
|
RegisterAccountDirectoryScopeResolver(AccountDirectoryScopeResolver) error
|
|
}
|