- WorkspaceConfig in der Instanzkonfiguration: Id, Name, Zweck, Eigentuemer-Einheit, Mitglieder (Einheit oder Agent, Stufe Read/Write/ Manage, Untereinheiten ein/aus), geschuetzte Pfade. Das Recht steht am Bereich, nicht am Agenten. - OrgChart: AccessTo, WorkspacesFor, UnitWorkspace; Problems nennt ungueltige Ids und tote Verweise. WorkspaceLayout: Bereiche liegen unter Agents/SharedWorkspaces/<id>/, neben dem unveraenderten SharedWorkspace. - FileRW: workspace ist ein Name - personal, shared (wie bisher ueber sharedAccessLevel), unit (eigene Einheit) oder eine Bereichs-Id. Ein unbekannter und ein nicht erlaubter Bereich bekommen dieselbe Antwort. Loeschen braucht Manage wie frueher Admin. Der #662-Hinweis sucht in allen erlaubten Bereichen. - Mit Einheiten ist shared:/tasks/ fuer FileRW gesperrt: Aufgaben laufen ueber das Brett, sonst umginge eine direkt geschriebene Datei Brett- und Adressbuchpruefung. Ohne Einheiten unveraendert. - Organisationsabschnitt im Prompt nennt die Bereiche mit Stufe und Zweck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.6 KiB
C#
57 lines
2.6 KiB
C#
using ClawdDotNet.Core.Config;
|
|
|
|
namespace ClawdDotNet.Core.Organisation;
|
|
|
|
/// <summary>#684: A workspace an agent may use, and how far.</summary>
|
|
/// <param name="IsOwnUnit">The workspace of the agent's own unit — reachable as <c>unit</c>.</param>
|
|
public sealed record WorkspaceGrant(WorkspaceConfig Workspace, WorkspaceAccess Access, bool IsOwnUnit);
|
|
|
|
/// <summary>
|
|
/// #684: Where the workspaces live on disk, and which names are taken.
|
|
///
|
|
/// <para>The instance's one shared folder is <c>Agents/SharedWorkspace</c>, and it stays
|
|
/// there: FTP, RocketChat, the agent editor, the task files and the backups all find it by
|
|
/// that path. The workspaces with member lists live beside it, one folder each under
|
|
/// <c>Agents/SharedWorkspaces/</c>. Found from the shared folder's path, which every tool
|
|
/// context already carries, so nothing new has to be passed around.</para>
|
|
/// </summary>
|
|
public static class WorkspaceLayout
|
|
{
|
|
public const string Personal = "personal";
|
|
public const string Shared = "shared";
|
|
|
|
/// <summary>The own unit's workspace, without having to know the unit's id.</summary>
|
|
public const string Unit = "unit";
|
|
|
|
/// <summary>The folder next to <c>SharedWorkspace</c> that holds the workspaces.</summary>
|
|
public const string ContainerFolder = "SharedWorkspaces";
|
|
|
|
/// <summary>Names a workspace cannot have — they mean something else in FileRW.</summary>
|
|
public static readonly IReadOnlyList<string> Reserved = [Personal, Shared, Unit];
|
|
|
|
/// <summary>Letters, digits, '-' and '_' — the same rule as for unit ids, since a unit's
|
|
/// workspace carries the unit's id — and not one of the reserved names.</summary>
|
|
public static bool IsValidId(string? id)
|
|
=> !string.IsNullOrWhiteSpace(id)
|
|
&& id.Length <= 64
|
|
&& id.All(c => char.IsLetterOrDigit(c) || c is '-' or '_')
|
|
&& !Reserved.Contains(id, StringComparer.OrdinalIgnoreCase);
|
|
|
|
/// <summary>
|
|
/// The folder of a workspace, from the path of the instance's shared folder;
|
|
/// <c>null</c> when that is not configured or the id is not valid.
|
|
/// </summary>
|
|
public static string? PathOf(string? sharedWorkspacePath, string workspaceId)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(sharedWorkspacePath) || !IsValidId(workspaceId))
|
|
return null;
|
|
|
|
var shared = Path.GetFullPath(sharedWorkspacePath)
|
|
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
|
var agentsDirectory = Path.GetDirectoryName(shared);
|
|
return agentsDirectory is null
|
|
? null
|
|
: Path.Combine(agentsDirectory, ContainerFolder, workspaceId);
|
|
}
|
|
}
|