Skip to content

Resource share/revoke contract (ResourceAccessMappingPayload) is unmodelled; its rename silently no-opped every consumer #1144

Description

@simihablo

Summary

The resource share / revoke contract - POST /api/resources/{resourceType}/{resourceId}/share and its ResourceAccessMappingPayload / Actor bodies - is not modelled anywhere in meshery/schemas. It exists only as Go structs in meshery-cloud:

server/models/model_resource_access_mapping_payload.go:

type Actor struct {
    ActorId   core.Uuid `json:"actorId,omitempty"`
    ActorType string    `json:"actorType,omitempty"`
}

type ResourceAccessMappingPayload struct {
    GrantAccess  []Actor `json:"grantAccess,omitempty"`
    RevokeAccess []Actor `json:"revokeAccess,omitempty"`
    NotifyUsers  bool    `json:"notifyUsers,omitempty"`
}

grep -rn "grantAccess" schemas/ in this repo returns nothing.

Why this one is worth modelling

This endpoint has the worst possible failure mode for an unmodelled contract. HandleResourceShare decodes with a strict json.Unmarshal into the struct above, whose every field carries omitempty, and then answers 200 regardless. An unrecognised key is not an error - it is dropped, and the caller is told the share succeeded.

That is not hypothetical. Sistent's ShareModal - which is upstream of Meshery UI, Layer5 Cloud UI and Kanvas - was posting the pre-flip snake_case body:

{ "grant_access": [{ "actor_id": "...", "actor_type": "user" }], "revoke_access": [], "notify_users": true }

against a server that has expected grantAccess / actorId / actorType / notifyUsers since the Phase 4 camelCase flip merged on 2026-04-28. Every "Design shared with ..." toast since then was reporting success on a request that granted nothing. Nothing on either side could catch it: sistent hands the body to a host-supplied RTK mutator typed any, and the server never rejects.

Had this contract been generated from schemas, the rename would have been a compile error in every consumer instead of a silent no-op for three months. Fixed downstream in layer5io/sistent#1780, which keeps a local type with a pointer to this issue.

Suggested resolution

Add Actor, ResourceAccessMappingPayload and the share/revoke operations to the appropriate construct (the resource-access mapping is org-scoped and touches design, filter and view resource types, so v1beta3 alongside the design construct or its own resource_access construct both seem defensible), and have meshery-cloud alias the generated Go types the way it now does for Team.

Filed from the sistent schema-consumer audit (layer5io/sistent#1780).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions