Documentation
¶
Overview ¶
Package group — GroupService + member-management.
Index ¶
- type AddMemberInput
- type AddMemberUseCase
- type CreateGroupUseCase
- func (u *CreateGroupUseCase) Execute(ctx context.Context, g domain.Group) (*operations.Operation, error)
- func (u *CreateGroupUseCase) WithObjectReconciler(r ObjectReconciler) *CreateGroupUseCase
- func (u *CreateGroupUseCase) WithRelationStore(relations clients.RelationStore, logger *slog.Logger) *CreateGroupUseCase
- type DeleteGroupUseCase
- type GetGroupUseCase
- type Handler
- func (h *Handler) AddMember(ctx context.Context, req *iamv1.AddGroupMemberRequest) (*operationpb.Operation, error)
- func (h *Handler) Create(ctx context.Context, req *iamv1.CreateGroupRequest) (*operationpb.Operation, error)
- func (h *Handler) Delete(ctx context.Context, req *iamv1.DeleteGroupRequest) (*operationpb.Operation, error)
- func (h *Handler) Get(ctx context.Context, req *iamv1.GetGroupRequest) (*iamv1.Group, error)
- func (h *Handler) List(ctx context.Context, req *iamv1.ListGroupsRequest) (*iamv1.ListGroupsResponse, error)
- func (h *Handler) ListMembers(ctx context.Context, req *iamv1.ListGroupMembersRequest) (*iamv1.ListGroupMembersResponse, error)
- func (h *Handler) ListOperations(ctx context.Context, req *iamv1.ListGroupOperationsRequest) (*iamv1.ListGroupOperationsResponse, error)
- func (h *Handler) RemoveMember(ctx context.Context, req *iamv1.RemoveGroupMemberRequest) (*operationpb.Operation, error)
- func (h *Handler) Update(ctx context.Context, req *iamv1.UpdateGroupRequest) (*operationpb.Operation, error)
- func (h *Handler) WithListOperations(uc *shared.ListOperationsUseCase) *Handler
- type ListGroupsUseCase
- func (u *ListGroupsUseCase) Execute(ctx context.Context, f repogroup.ListFilter) ([]domain.Group, string, error)
- func (u *ListGroupsUseCase) WithListScanRecorder(rec shared.ListScanRecorder) *ListGroupsUseCase
- func (u *ListGroupsUseCase) WithRelationStore(relations clients.RelationQueries) *ListGroupsUseCase
- type ListMembersInput
- type ListMembersOutput
- type ListMembersUseCase
- type ObjectReconciler
- type Reader
- type RemoveMemberInput
- type RemoveMemberUseCase
- type Repo
- type UpdateGroupInput
- type UpdateGroupUseCase
- type Writer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AddMemberInput ¶
type AddMemberUseCase ¶
type AddMemberUseCase struct {
// contains filtered or unexported fields
}
func NewAddMemberUseCase ¶
func NewAddMemberUseCase(r Repo, opsRepo operations.Repo) *AddMemberUseCase
func (*AddMemberUseCase) Execute ¶
func (u *AddMemberUseCase) Execute(ctx context.Context, in AddMemberInput) (*operations.Operation, error)
type CreateGroupUseCase ¶
type CreateGroupUseCase struct {
// contains filtered or unexported fields
}
func NewCreateGroupUseCase ¶
func NewCreateGroupUseCase(r Repo, opsRepo operations.Repo) *CreateGroupUseCase
func (*CreateGroupUseCase) Execute ¶
func (u *CreateGroupUseCase) Execute(ctx context.Context, g domain.Group) (*operations.Operation, error)
func (*CreateGroupUseCase) WithObjectReconciler ¶
func (u *CreateGroupUseCase) WithObjectReconciler(r ObjectReconciler) *CreateGroupUseCase
WithObjectReconciler wires the post-commit synchronous per-object materializer (rbac-contract-a-fix, C-01b). nil-safe.
func (*CreateGroupUseCase) WithRelationStore ¶
func (u *CreateGroupUseCase) WithRelationStore(relations clients.RelationStore, logger *slog.Logger) *CreateGroupUseCase
WithRelationStore wires the group→account hierarchy-tuple writer.
type DeleteGroupUseCase ¶
type DeleteGroupUseCase struct {
// contains filtered or unexported fields
}
func NewDeleteGroupUseCase ¶
func NewDeleteGroupUseCase(r Repo, opsRepo operations.Repo) *DeleteGroupUseCase
func (*DeleteGroupUseCase) Execute ¶
func (u *DeleteGroupUseCase) Execute(ctx context.Context, id domain.GroupID) (*operations.Operation, error)
type GetGroupUseCase ¶
type GetGroupUseCase struct {
// contains filtered or unexported fields
}
func NewGetGroupUseCase ¶
func NewGetGroupUseCase(r Repo) *GetGroupUseCase
func (*GetGroupUseCase) Execute ¶
Execute — sync read.
Authz (Design B, D-6/D-9): the caller must hold `v_get` on iam_group:<id> OR be a cluster-admin. Otherwise (incl. anonymous) → NotFound (hide existence; no enumeration). Replaces the legacy owner-only gate that denied a delegate granted `iam.group.get`.
func (*GetGroupUseCase) WithRelationStore ¶
func (u *GetGroupUseCase) WithRelationStore(relations clients.RelationStore) *GetGroupUseCase
WithRelationStore wires the FGA client authorizing the read via the verb-bearing `v_get` relation on iam_group:<id> (+ cluster-admin short-circuit). Without it a non-cluster-admin Get fails closed.
type Handler ¶
type Handler struct {
iamv1.UnimplementedGroupServiceServer
// contains filtered or unexported fields
}
func NewHandler ¶
func NewHandler(c *CreateGroupUseCase, u *UpdateGroupUseCase, d *DeleteGroupUseCase, g *GetGroupUseCase, l *ListGroupsUseCase, am *AddMemberUseCase, rm *RemoveMemberUseCase, lm *ListMembersUseCase) *Handler
func (*Handler) AddMember ¶
func (h *Handler) AddMember(ctx context.Context, req *iamv1.AddGroupMemberRequest) (*operationpb.Operation, error)
func (*Handler) Create ¶
func (h *Handler) Create(ctx context.Context, req *iamv1.CreateGroupRequest) (*operationpb.Operation, error)
func (*Handler) Delete ¶
func (h *Handler) Delete(ctx context.Context, req *iamv1.DeleteGroupRequest) (*operationpb.Operation, error)
func (*Handler) List ¶
func (h *Handler) List(ctx context.Context, req *iamv1.ListGroupsRequest) (*iamv1.ListGroupsResponse, error)
List — sync read with pagination.
Формат страницы судится по СЫРОМУ запросу первым стейтментом: сужение int64→int32 ниже насыщающее, и отрицательный page_size превратился бы в 0 («умолчание») до того, как его кто-либо увидит.
func (*Handler) ListMembers ¶
func (h *Handler) ListMembers(ctx context.Context, req *iamv1.ListGroupMembersRequest) (*iamv1.ListGroupMembersResponse, error)
func (*Handler) ListOperations ¶
func (h *Handler) ListOperations(ctx context.Context, req *iamv1.ListGroupOperationsRequest) (*iamv1.ListGroupOperationsResponse, error)
func (*Handler) RemoveMember ¶
func (h *Handler) RemoveMember(ctx context.Context, req *iamv1.RemoveGroupMemberRequest) (*operationpb.Operation, error)
func (*Handler) Update ¶
func (h *Handler) Update(ctx context.Context, req *iamv1.UpdateGroupRequest) (*operationpb.Operation, error)
func (*Handler) WithListOperations ¶
func (h *Handler) WithListOperations(uc *shared.ListOperationsUseCase) *Handler
WithListOperations wires the per-resource operation-listing use-case.
type ListGroupsUseCase ¶
type ListGroupsUseCase struct {
// contains filtered or unexported fields
}
func NewListGroupsUseCase ¶
func NewListGroupsUseCase(r Repo) *ListGroupsUseCase
func (*ListGroupsUseCase) Execute ¶
func (u *ListGroupsUseCase) Execute(ctx context.Context, f repogroup.ListFilter) ([]domain.Group, string, error)
func (*ListGroupsUseCase) WithListScanRecorder ¶
func (u *ListGroupsUseCase) WithListScanRecorder(rec shared.ListScanRecorder) *ListGroupsUseCase
WithRelationStore wires the FGA ListObjects client (паритет с account/project/service_account/role List). WithListScanRecorder провязывает съём стоимости страницы (#653).
func (*ListGroupsUseCase) WithRelationStore ¶
func (u *ListGroupsUseCase) WithRelationStore(relations clients.RelationQueries) *ListGroupsUseCase
type ListMembersInput ¶
ListMembersInput — one page of a group's membership.
type ListMembersOutput ¶
type ListMembersOutput struct {
Members []domain.GroupMember
NextPageToken string
}
ListMembersOutput — the page plus the continuation token, empty on the last page.
type ListMembersUseCase ¶
type ListMembersUseCase struct {
// contains filtered or unexported fields
}
func NewListMembersUseCase ¶
func NewListMembersUseCase(r Repo) *ListMembersUseCase
func (*ListMembersUseCase) Execute ¶
func (u *ListMembersUseCase) Execute(ctx context.Context, in ListMembersInput) (ListMembersOutput, error)
Execute returns one page of the membership.
page_size is validated HERE, before the storage is touched: an out-of-range value is a refusal, never a clamp (a clamped page makes the caller believe it received everything it asked for), and the refusal must not depend on how far down the call the storage happens to check. The adapter keeps its own check as the authoritative backstop.
Then the group NAMED IN THE REQUEST is re-asked about, on `v_list` — the same relation the front door requires of this RPC, so a caller admitted there is admitted here. Both sibling reads of this resource already do it (`Get` on `v_get`, `List` through the per-object page filter); this one did not, and it is also the only one of the three whose name the List-surface analyser cannot see. A denial is the resource's own miss, verbatim, so it cannot be told from the group not existing; a model that could not be ASKED is an outage, never a miss.
func (*ListMembersUseCase) WithRelationStore ¶
func (u *ListMembersUseCase) WithRelationStore(relations authzguard.RelationChecker) *ListMembersUseCase
WithRelationStore wires the relation-Check port. Unwired, the roster is served to nobody: a read whose remaining authorization lives one layer up must not quietly become a read with none.
type ObjectReconciler ¶
type ObjectReconciler interface {
// ReconcileObjectForward is the ADDITIVE forward fast-path for the freshly-created
// group-AS-OBJECT (iam.group): it materializes ONLY that new group's per-object
// owner/admin tuples across the matching bindings while holding NO advisory lock at
// all (neither EXCLUSIVE nor SHARE, no O(scope) recompute), the throughput fix for the owner-tuple
// materialization lag under a parallel group-create burst. It transparently delegates
// to the FULL ReconcileObject if the object already has members (delete-stale guard).
ReconcileObjectForwardNoStale(ctx context.Context, objectType, objectID string) error
// ReconcileObjectForward — СТОРОЖЕВОЙ вход того же прохода: он сперва читает,
// есть ли у объекта члены, и при непустом наборе уходит на полный проход ради
// снятия устаревших. Пути СОЗДАНИЯ он не нужен (доказательство — выше), но
// остаётся в порту: его зовёт правка того же пакета, где прежние факты есть
// и снятие устаревших — как раз предмет.
ReconcileObjectForward(ctx context.Context, objectType, objectID string) error
// ReconcileObject is the FULL EXCLUSIVE object-fan-out (async at-least-once backstop —
// delete-stale / audit / sweep), driven by the reconcile worker off the co-committed
// reconcile-outbox event, not the create hot-path.
ReconcileObject(ctx context.Context, objectType, objectID string) error
}
ObjectReconciler — narrow port (rbac-contract-a-fix, C-01b): SYNCHRONOUSLY materialize the per-object access of every binding whose selector matches a freshly-created iam-native object, right after Create commits. Under the flat rights model (Contract-A) the `<rel> from account` ACCESS cascade on iam leaf types is gone, so the owner's / account-admin's per-object admin/v_* tuple is materialized per-object by the reconciler — and the async event drain races a client that GETs the object right after the Operation reports done. The sync call closes that race. Implemented by reconcile.Reconciler (the SAME single materialization path the worker drives). nil-safe: when unwired the co-committed reconcile event + periodic sweep still materialize it, just not synchronously.
type Reader ¶
type Reader = kanamerepo.Reader
type RemoveMemberInput ¶
type RemoveMemberUseCase ¶
type RemoveMemberUseCase struct {
// contains filtered or unexported fields
}
func NewRemoveMemberUseCase ¶
func NewRemoveMemberUseCase(r Repo, opsRepo operations.Repo) *RemoveMemberUseCase
func (*RemoveMemberUseCase) Execute ¶
func (u *RemoveMemberUseCase) Execute(ctx context.Context, in RemoveMemberInput) (*operations.Operation, error)
type Repo ¶
type Repo = kanamerepo.Repository
type UpdateGroupInput ¶
type UpdateGroupUseCase ¶
type UpdateGroupUseCase struct {
// contains filtered or unexported fields
}
func NewUpdateGroupUseCase ¶
func NewUpdateGroupUseCase(r Repo, opsRepo operations.Repo) *UpdateGroupUseCase
func (*UpdateGroupUseCase) Execute ¶
func (u *UpdateGroupUseCase) Execute(ctx context.Context, in UpdateGroupInput) (*operations.Operation, error)
func (*UpdateGroupUseCase) WithObjectReconciler ¶
func (u *UpdateGroupUseCase) WithObjectReconciler(r ObjectReconciler, logger *slog.Logger) *UpdateGroupUseCase
WithObjectReconciler wires the post-commit per-object materializer used on a LABEL change (parity with the cross-service RegisterResource re-register path — see doUpdate). Optional; nil keeps the queue-only behaviour. The logger is used only to report a failed pass (the durable event + sweep still re-converge).
type Writer ¶
type Writer = kanamerepo.Writer