anbaric-tsapi 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/api/actions/AgenticAction.ts +24 -0
- package/src/api/actors/Actor.ts +1 -1
- package/src/api/actors/SystemActor.ts +13 -0
- package/src/api/actors/agents/Agent.ts +32 -0
- package/src/api/actors/agents/AgentMessage.ts +8 -0
- package/src/api/actors/agents/AgentRequest.ts +10 -0
- package/src/api/auditing/Auditor.ts +11 -4
- package/src/api/auditing/NoOpAuditor.ts +15 -0
- package/src/api/cloud/AuditRecord.ts +4 -3
- package/src/api/documents/JsonStore.ts +38 -5
- package/src/api/jobs/Job.ts +7 -29
- package/src/api/jobs/JobPersistence.ts +84 -6
- package/src/api/jobs/JobSerialization.ts +2 -6
- package/src/api/secrets/SecretStore.ts +39 -5
- package/src/index.ts +6 -1
- package/src/api/jobs/JobTransition.ts +0 -7
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Agent} from "../actors/agents/Agent";
|
|
2
|
+
import {AgentRequest} from "../actors/agents/AgentRequest";
|
|
3
|
+
import {Job} from "../jobs/Job";
|
|
4
|
+
import {Action} from "./Action";
|
|
5
|
+
|
|
6
|
+
/* An action whose properties are generated by an agent. run builds a request
|
|
7
|
+
from the job and hands it to the agent's client; the structured result
|
|
8
|
+
becomes the property map. Subclasses decide how the request is composed. */
|
|
9
|
+
abstract class AgenticAction extends Action {
|
|
10
|
+
|
|
11
|
+
protected agent : Agent;
|
|
12
|
+
|
|
13
|
+
constructor(name : string, agent : Agent, description : string = "", id? : string) {
|
|
14
|
+
super(name, agent, description, id);
|
|
15
|
+
this.agent = agent;
|
|
16
|
+
this.run = async (job : Job) =>
|
|
17
|
+
new Map(Object.entries(await this.agent.client.generate(this.requestFor(job))));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
protected abstract requestFor(job : Job) : AgentRequest;
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { AgenticAction }
|
package/src/api/actors/Actor.ts
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {Actor} from "../Actor";
|
|
2
|
+
import {AgentRequest} from "./AgentRequest";
|
|
3
|
+
|
|
4
|
+
/* An agent is a light actor: identity only, used for auditing and
|
|
5
|
+
authorization like any other actor. The functional model detail lives in
|
|
6
|
+
its Client collaborator, keeping the actor itself pure data. */
|
|
7
|
+
class Agent implements Actor {
|
|
8
|
+
|
|
9
|
+
readonly type = "AGENT" as const;
|
|
10
|
+
readonly id : string;
|
|
11
|
+
readonly role : string;
|
|
12
|
+
readonly client : Agent.Client;
|
|
13
|
+
|
|
14
|
+
constructor(id : string, role : string, client : Agent.Client) {
|
|
15
|
+
this.id = id;
|
|
16
|
+
this.role = role;
|
|
17
|
+
this.client = client;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
namespace Agent {
|
|
23
|
+
|
|
24
|
+
export abstract class Client {
|
|
25
|
+
|
|
26
|
+
abstract generate(request : AgentRequest) : Promise<Record<string, any>>;
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { Agent }
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import {Actor} from "../actors/Actor";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
enum AuditInteraction {
|
|
4
|
+
CREATE = "CREATE",
|
|
5
|
+
UPDATE_PROPERTIES = "UPDATE_PROPERTIES",
|
|
6
|
+
CHANGE_STATE = "CHANGE_STATE",
|
|
7
|
+
DELETE = "DELETE",
|
|
8
|
+
READ = "READ",
|
|
9
|
+
LIST = "LIST",
|
|
10
|
+
}
|
|
4
11
|
|
|
5
12
|
interface Auditor {
|
|
6
13
|
|
|
7
|
-
audit(
|
|
8
|
-
|
|
14
|
+
audit(resourceType : string, resourceId : string, actor : Actor, interaction : AuditInteraction[],
|
|
15
|
+
description : string, details : any) : Promise<void>;
|
|
9
16
|
|
|
10
17
|
}
|
|
11
18
|
|
|
12
|
-
export
|
|
19
|
+
export { AuditInteraction, Auditor }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {Actor} from "../actors/Actor";
|
|
2
|
+
import {AuditInteraction, Auditor} from "./Auditor";
|
|
3
|
+
|
|
4
|
+
/* An auditor that records nothing. Used by the persistence instances that sit
|
|
5
|
+
behind the HTTP API, where the app-facing store on the other side has
|
|
6
|
+
already audited the interaction. */
|
|
7
|
+
class NoOpAuditor implements Auditor {
|
|
8
|
+
|
|
9
|
+
async audit(_resourceType : string, _resourceId : string, _actor : Actor, _interaction : AuditInteraction[],
|
|
10
|
+
_description : string, _details : any) : Promise<void> {
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { NoOpAuditor }
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {AuditInteraction} from "../auditing/Auditor";
|
|
2
2
|
|
|
3
3
|
type AuditRecord = {
|
|
4
4
|
id? : string,
|
|
5
|
-
|
|
5
|
+
resourceType : string,
|
|
6
|
+
resourceId : string,
|
|
6
7
|
actorId : string,
|
|
7
8
|
actorType : string,
|
|
8
|
-
|
|
9
|
+
interaction : AuditInteraction[],
|
|
9
10
|
description : string,
|
|
10
11
|
details : any,
|
|
11
12
|
at? : string,
|
|
@@ -1,9 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
import {Actor} from "../actors/Actor";
|
|
2
|
+
import {AuditInteraction, Auditor} from "../auditing/Auditor";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/* A schema-validated JSON document store that audits every interaction, keyed
|
|
5
|
+
by collection and id. Public methods audit then defer to ...Internal. */
|
|
6
|
+
abstract class JsonStore {
|
|
7
|
+
|
|
8
|
+
constructor(protected auditor : Auditor, protected collection : string = "documents") {
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async create(actor : Actor, id : string, document : any) : Promise<void> {
|
|
12
|
+
await this.auditor.audit("document", `${this.collection}/${id}`, actor, [AuditInteraction.CREATE], "Document created", document);
|
|
13
|
+
await this.saveInternal(id, document);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async save(actor : Actor, changeDescription : string, id : string, document : any) : Promise<void> {
|
|
17
|
+
await this.auditor.audit("document", `${this.collection}/${id}`, actor, [AuditInteraction.UPDATE_PROPERTIES], changeDescription, document);
|
|
18
|
+
await this.saveInternal(id, document);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async retrieve(id : string, actor : Actor) : Promise<any> {
|
|
22
|
+
await this.auditor.audit("document", `${this.collection}/${id}`, actor, [AuditInteraction.READ], "", null);
|
|
23
|
+
return this.retrieveInternal(id);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async delete(id : string, actor : Actor) : Promise<void> {
|
|
27
|
+
await this.auditor.audit("document", `${this.collection}/${id}`, actor, [AuditInteraction.DELETE], "", null);
|
|
28
|
+
await this.deleteInternal(id);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async list(actor : Actor, pageSize? : number, page? : number) : Promise<Array<any>> {
|
|
32
|
+
await this.auditor.audit("document", `${this.collection}/*`, actor, [AuditInteraction.LIST], "", null);
|
|
33
|
+
return this.listInternal(pageSize, page);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
protected abstract saveInternal(id : string, document : any) : Promise<void>;
|
|
37
|
+
protected abstract retrieveInternal(id : string) : Promise<any>;
|
|
38
|
+
protected abstract deleteInternal(id : string) : Promise<void>;
|
|
39
|
+
protected abstract listInternal(pageSize? : number, page? : number) : Promise<Array<any>>;
|
|
7
40
|
|
|
8
41
|
}
|
|
9
42
|
|
package/src/api/jobs/Job.ts
CHANGED
|
@@ -1,48 +1,26 @@
|
|
|
1
1
|
import {Transition} from "../transitions/Transition";
|
|
2
|
-
import {JobTransition} from "./JobTransition";
|
|
3
2
|
|
|
4
3
|
class Job {
|
|
5
4
|
|
|
6
5
|
readonly id : string;
|
|
7
|
-
|
|
8
|
-
properties : Map<string, any>;
|
|
6
|
+
readonly state: string;
|
|
7
|
+
readonly properties : Map<string, any>;
|
|
9
8
|
readonly workflowId? : string;
|
|
10
9
|
readonly startedAt : Date;
|
|
11
10
|
readonly startedBy : string;
|
|
12
|
-
lastUpdated : Date;
|
|
13
|
-
readonly transitions : Array<JobTransition>;
|
|
11
|
+
readonly lastUpdated : Date;
|
|
14
12
|
|
|
15
|
-
constructor(id : string, properties : Map<string, any> = new Map(),
|
|
13
|
+
constructor(id : string, properties : Map<string, any> = new Map(), state: string, workflowId? : string,
|
|
16
14
|
startedBy : string = "system", startedAt : Date = new Date(),
|
|
17
|
-
lastUpdated : Date = startedAt
|
|
15
|
+
lastUpdated : Date = startedAt) {
|
|
16
|
+
|
|
18
17
|
this.id = id;
|
|
19
18
|
this.properties = properties;
|
|
20
|
-
this.state =
|
|
19
|
+
this.state = state;
|
|
21
20
|
this.workflowId = workflowId;
|
|
22
21
|
this.startedBy = startedBy;
|
|
23
22
|
this.startedAt = startedAt;
|
|
24
23
|
this.lastUpdated = lastUpdated;
|
|
25
|
-
this.transitions = transitions;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
private setState(stateId : string) : void {
|
|
29
|
-
this.state = stateId;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get stateId() : string | undefined {
|
|
33
|
-
return this.state;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
transition(transition : Transition, actor : string = this.workflowId ?? "state-machine") : boolean {
|
|
37
|
-
|
|
38
|
-
if (transition.predicate(this)) {
|
|
39
|
-
this.transitions.push({ from: this.state, to: transition.to, actor });
|
|
40
|
-
this.setState(transition.to);
|
|
41
|
-
this.lastUpdated = new Date();
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return false;
|
|
46
24
|
}
|
|
47
25
|
|
|
48
26
|
}
|
|
@@ -1,12 +1,90 @@
|
|
|
1
|
+
import {Actor} from "../actors/Actor";
|
|
2
|
+
import {AuditInteraction, Auditor} from "../auditing/Auditor";
|
|
1
3
|
import {Job} from "./Job";
|
|
4
|
+
import {SystemActor} from "../actors/SystemActor";
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
/* Persists jobs and audits every interaction. Public methods record the
|
|
7
|
+
interaction against the injected auditor and then defer to the abstract
|
|
8
|
+
...Internal methods a concrete store implements. */
|
|
9
|
+
abstract class JobPersistence {
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
constructor(protected auditor : Auditor) {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async create(actor : Actor,
|
|
15
|
+
job : Job) : Promise<void> {
|
|
16
|
+
|
|
17
|
+
await this.auditor.audit("job", job.id, actor, [AuditInteraction.CREATE], "Job created", job);
|
|
18
|
+
|
|
19
|
+
this.saveInternal(job);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async save(actor : Actor,
|
|
23
|
+
changeDescription : string,
|
|
24
|
+
job : Job,
|
|
25
|
+
properties? : Map<string, any>,
|
|
26
|
+
state? : string) : Promise<void> {
|
|
27
|
+
|
|
28
|
+
const change = {
|
|
29
|
+
properties: properties ? this.generatePropertiesDiff(job.properties, properties) : undefined,
|
|
30
|
+
state: state ? {from : job.state, to : state} : undefined
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const interaction = [];
|
|
34
|
+
if (properties) interaction.push(AuditInteraction.UPDATE_PROPERTIES);
|
|
35
|
+
if (state) interaction.push(AuditInteraction.CHANGE_STATE);
|
|
36
|
+
|
|
37
|
+
await this.auditor.audit("job", job.id, actor, interaction, changeDescription, change);
|
|
38
|
+
|
|
39
|
+
const updatedJob = new Job(
|
|
40
|
+
job.id,
|
|
41
|
+
properties ? this.updateProperties(job.properties, properties) : job.properties,
|
|
42
|
+
state ? state : job.state,
|
|
43
|
+
job.workflowId,
|
|
44
|
+
job.startedBy,
|
|
45
|
+
job.startedAt,
|
|
46
|
+
new Date()
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
this.saveInternal(updatedJob);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private generatePropertiesDiff(oldVersion : Map<string, any>, newVersion : Map<string, any>) : Map<string, {from: any, to: any}> {
|
|
53
|
+
const diff: Map<string, { from: any; to: any; }> = new Map();
|
|
54
|
+
|
|
55
|
+
for (const [key, value] of newVersion) {
|
|
56
|
+
diff.set(key, {from: oldVersion.get(key), to: value});
|
|
57
|
+
}
|
|
58
|
+
return diff;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private updateProperties(oldVersion : Map<string, any>, newVersion : Map<string, any>) : Map<string, any> {
|
|
62
|
+
const updated = new Map(oldVersion);
|
|
63
|
+
for (const [key, value] of newVersion) {
|
|
64
|
+
updated.set(key, value);
|
|
65
|
+
}
|
|
66
|
+
return updated;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async retrieve(id : string, actor : Actor) : Promise<Job> {
|
|
70
|
+
await this.auditor.audit("job", id, actor, [AuditInteraction.READ], "", null);
|
|
71
|
+
return this.retrieveInternal(id);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async delete(id : string, actor : Actor) : Promise<void> {
|
|
75
|
+
await this.auditor.audit("job", id, actor, [AuditInteraction.DELETE], "", null);
|
|
76
|
+
await this.deleteInternal(id);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async list(actor : Actor, pageSize? : number, page? : number) : Promise<Array<Job>> {
|
|
80
|
+
await this.auditor.audit("job", "*", actor, [AuditInteraction.LIST], "", null);
|
|
81
|
+
return this.listInternal(pageSize, page);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
protected abstract saveInternal(job : Job) : Promise<void>;
|
|
85
|
+
protected abstract retrieveInternal(id : string) : Promise<Job>;
|
|
86
|
+
protected abstract deleteInternal(id : string) : Promise<void>;
|
|
87
|
+
protected abstract listInternal(pageSize? : number, page? : number) : Promise<Array<Job>>;
|
|
10
88
|
|
|
11
89
|
}
|
|
12
90
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {Job} from "./Job";
|
|
2
|
-
import {JobTransition} from "./JobTransition";
|
|
3
2
|
|
|
4
3
|
type SerializedJob = {
|
|
5
4
|
id : string,
|
|
@@ -9,26 +8,23 @@ type SerializedJob = {
|
|
|
9
8
|
startedAt? : string,
|
|
10
9
|
startedBy? : string,
|
|
11
10
|
lastUpdated? : string,
|
|
12
|
-
transitions? : Array<JobTransition>,
|
|
13
11
|
};
|
|
14
12
|
|
|
15
13
|
const serializeJob = (job : Job) : SerializedJob => ({
|
|
16
14
|
id: job.id,
|
|
17
|
-
state: job.
|
|
15
|
+
state: job.state,
|
|
18
16
|
properties: Object.fromEntries(job.properties),
|
|
19
17
|
workflowId: job.workflowId,
|
|
20
18
|
startedAt: job.startedAt.toISOString(),
|
|
21
19
|
startedBy: job.startedBy,
|
|
22
20
|
lastUpdated: job.lastUpdated.toISOString(),
|
|
23
|
-
transitions: job.transitions,
|
|
24
21
|
});
|
|
25
22
|
|
|
26
23
|
const deserializeJob = (serialized : SerializedJob) : Job => {
|
|
27
24
|
const startedAt = serialized.startedAt ? new Date(serialized.startedAt) : new Date();
|
|
28
25
|
return new Job(serialized.id, new Map(Object.entries(serialized.properties)), serialized.state,
|
|
29
26
|
serialized.workflowId, serialized.startedBy ?? "system", startedAt,
|
|
30
|
-
serialized.lastUpdated ? new Date(serialized.lastUpdated) : startedAt
|
|
31
|
-
serialized.transitions ?? []);
|
|
27
|
+
serialized.lastUpdated ? new Date(serialized.lastUpdated) : startedAt);
|
|
32
28
|
};
|
|
33
29
|
|
|
34
30
|
export { serializeJob, deserializeJob };
|
|
@@ -1,9 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
import {Actor} from "../actors/Actor";
|
|
2
|
+
import {AuditInteraction, Auditor} from "../auditing/Auditor";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/* Stores named secrets and audits every interaction. The secret value is
|
|
5
|
+
never included in an audit record. Public methods audit then defer to the
|
|
6
|
+
abstract ...Internal methods. */
|
|
7
|
+
abstract class SecretStore {
|
|
8
|
+
|
|
9
|
+
constructor(protected auditor : Auditor) {
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async create(actor : Actor, name : string, value : string) : Promise<void> {
|
|
13
|
+
await this.auditor.audit("secret", name, actor, [AuditInteraction.CREATE], "Secret created", null);
|
|
14
|
+
await this.saveInternal(name, value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async save(actor : Actor, changeDescription : string, name : string, value : string) : Promise<void> {
|
|
18
|
+
await this.auditor.audit("secret", name, actor, [AuditInteraction.UPDATE_PROPERTIES], changeDescription, null);
|
|
19
|
+
await this.saveInternal(name, value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async retrieve(name : string, actor : Actor) : Promise<string> {
|
|
23
|
+
await this.auditor.audit("secret", name, actor, [AuditInteraction.READ], "", null);
|
|
24
|
+
return this.retrieveInternal(name);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async delete(name : string, actor : Actor) : Promise<void> {
|
|
28
|
+
await this.auditor.audit("secret", name, actor, [AuditInteraction.DELETE], "", null);
|
|
29
|
+
await this.deleteInternal(name);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async list(actor : Actor) : Promise<Array<string>> {
|
|
33
|
+
await this.auditor.audit("secret", "*", actor, [AuditInteraction.LIST], "", null);
|
|
34
|
+
return this.listInternal();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected abstract saveInternal(name : string, value : string) : Promise<void>;
|
|
38
|
+
protected abstract retrieveInternal(name : string) : Promise<string>;
|
|
39
|
+
protected abstract deleteInternal(name : string) : Promise<void>;
|
|
40
|
+
protected abstract listInternal() : Promise<Array<string>>;
|
|
7
41
|
|
|
8
42
|
}
|
|
9
43
|
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
export * from "./api/jobs/Job";
|
|
2
2
|
export * from "./api/jobs/JobPersistence"
|
|
3
3
|
export * from "./api/jobs/JobSerialization"
|
|
4
|
-
export * from "./api/jobs/JobTransition"
|
|
5
4
|
export * from "./api/jobs/PropertyDefinition"
|
|
6
5
|
export * from "./api/states/State"
|
|
7
6
|
export * from "./api/actions/Action"
|
|
7
|
+
export * from "./api/actions/AgenticAction"
|
|
8
|
+
export * from "./api/actors/agents/AgentMessage"
|
|
9
|
+
export * from "./api/actors/agents/AgentRequest"
|
|
10
|
+
export * from "./api/actors/agents/Agent"
|
|
8
11
|
export * from "./api/auditing/Auditor"
|
|
12
|
+
export * from "./api/auditing/NoOpAuditor"
|
|
9
13
|
export * from "./api/transitions/Transition"
|
|
10
14
|
export * from "./api/actors/Actor"
|
|
15
|
+
export * from "./api/actors/SystemActor"
|
|
11
16
|
export * from "./api/documents/JsonStore"
|
|
12
17
|
export * from "./api/secrets/SecretStore"
|
|
13
18
|
export * from "./api/documents/JsonSchema"
|