Fine-Grained Auth
Creating Resources
Create FGA resources through entity-backed sync or manual APIs.
The recommended path for protected application rows is to make the EF entity implement ISqlOSResourceEntity. When the app derives its DbContext from SqlOSDbContext<TContext>, SqlOS creates, updates, and deletes the backing SqlOSFgaResource row during SaveChanges / SaveChangesAsync.
public sealed class Workspace : ISqlOSResourceEntity
{
public Guid Id { get; set; }
public string ResourceId { get; set; } = "";
public string Name { get; set; } = "";
public string OrganizationId { get; set; } = "";
public string ResourceTypeId => "workspace";
public string ResourceName => Name;
public string ParentResourceId => $"org::{OrganizationId}";
public string? ResourceDescription => null;
public bool ResourceIsActive => true;
}Assign a stable ResourceId before saving the entity:
var workspaceId = Guid.NewGuid();
var workspace = new Workspace
{
Id = workspaceId,
ResourceId = $"workspace::{workspaceId:D}",
OrganizationId = organizationId,
Name = request.Name.Trim()
};
db.Workspaces.Add(workspace);
await db.SaveChangesAsync(ct);SqlOSDbContext<TContext> validates the resource type, parent resource, self-parenting, and obvious cycles before it writes the SqlOSFgaResource row.
Use manual resource APIs only for resources that are not represented by an application entity, such as tenant roots, organization roots, or external resources.
await db.ProvisionResourceWithIdAsync(
$"org::{organization.Id}",
resourceTypeId: "organization",
name: organization.Name,
parentResourceId: "root",
isActive: organization.IsActive,
cancellationToken: ct);For strict creates, use CreateResourceAsync(...) or CreateResourceWithIdAsync(...). For deletes, use DeleteResourceAsync(...); it deletes the resource and direct grants, but it does not cascade child resources.