Skip to content
This repository was archived by the owner on Aug 15, 2025. It is now read-only.

Commit 7568cb3

Browse files
committed
feat: Add [bare] polyproto-mls extension
1 parent b19b286 commit 7568cb3

File tree

7 files changed

+253
-1
lines changed

7 files changed

+253
-1
lines changed

polyproto/core/routes/federated_identity.tsp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import "./main.tsp";
77

88
using TypeSpec.Http;
99
using TypeSpec.Versioning;
10-
using polyproto.core;
1110

1211
namespace polyproto.core.Routes.FederatedIdentity {
1312
@tag("Federated Identity - Registration required")

polyproto/main.tsp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import "./chat/main.tsp";
22
import "./core/main.tsp";
3+
import "./mls/main.tsp";
34

45
namespace polyproto;

polyproto/mls/main.tsp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import "./types.tsp";
2+
import "./operations.tsp";
3+
import "../main.tsp";
4+
5+
using Http;
6+
using Versioning;
7+
using OpenAPI;
8+
9+
@service(#{ title: "polyproto chat APIs" })
10+
@info(#{
11+
license: #{
12+
name: "MIT License",
13+
url: "https://raw.githubusercontent.com/polyphony-chat/docs/refs/heads/main/LICENSE",
14+
},
15+
})
16+
@server("https://example.com", "Example endpoint")
17+
@route("/.p2/chat/v1/")
18+
@versioned(Version)
19+
namespace polyproto.mls;
20+
21+
enum Version {
22+
`v0.1.0-alpha.0`,
23+
}

polyproto/mls/operations.tsp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import "@typespec/rest";
2+
import "@typespec/openapi";
3+
import "@typespec/http";
4+
import "./main.tsp";
5+
import "../main.tsp";
6+
7+
using TypeSpec.Http;
8+
9+
namespace polyproto.mls.routes {
10+
/**
11+
* Create a new MLS group
12+
*/
13+
@post
14+
@route("/groups")
15+
op createGroup(@body keyPackage: KeyPackage): Group;
16+
17+
/**
18+
* Get information about an MLS group
19+
*/
20+
@get
21+
@route("/groups/{groupId}")
22+
op getGroup(@path groupId: string): Group;
23+
24+
/**
25+
* Submit a proposal to modify the group
26+
*/
27+
@post
28+
@route("/groups/{groupId}/proposals")
29+
op submitProposal(@path groupId: string, @body proposal: Proposal): void;
30+
31+
/**
32+
* Submit a commit to apply pending proposals
33+
*/
34+
@post
35+
@route("/groups/{groupId}/commits")
36+
op submitCommit(@path groupId: string, @body commit: Commit): Welcome;
37+
38+
/**
39+
* Get the current state of a group member
40+
*/
41+
@get
42+
@route("/groups/{groupId}/members/{memberId}")
43+
op getMember(@path groupId: string, @path memberId: string): GroupMember;
44+
45+
/**
46+
* Update a member's key package
47+
*/
48+
@put
49+
@route("/groups/{groupId}/members/{memberId}")
50+
op updateMember(
51+
@path groupId: string,
52+
@path memberId: string,
53+
@body keyPackage: KeyPackage,
54+
): void;
55+
56+
/**
57+
* Remove a member from the group
58+
*/
59+
@delete
60+
@route("/groups/{groupId}/members/{memberId}")
61+
op removeMember(@path groupId: string, @path memberId: string): void;
62+
63+
/**
64+
* Get all pending proposals for a group
65+
*/
66+
@get
67+
@route("/groups/{groupId}/proposals")
68+
op getProposals(@path groupId: string): Proposal[];
69+
70+
/**
71+
* Get the latest commit for a group
72+
*/
73+
@get
74+
@route("/groups/{groupId}/commits/latest")
75+
op getLatestCommit(@path groupId: string): Commit;
76+
}

polyproto/mls/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "polyproto-mls",
3+
"version": "0.1.0",
4+
"type": "module"
5+
}

polyproto/mls/tspconfig.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
emit:
2+
- "@typespec/openapi3"
3+
options:
4+
"@typespec/openapi3":
5+
emitter-output-dir: "{output-dir}/schema"
6+
openapi-versions:
7+
- "3.1.0"

polyproto/mls/types.tsp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import "@typespec/rest";
2+
import "@typespec/openapi";
3+
4+
namespace polyproto.mls;
5+
6+
/**
7+
* Represents a client's capabilities and provides keys for group operations
8+
*/
9+
model KeyPackage {
10+
@doc("Unique identifier for this key package")
11+
id: string;
12+
13+
@doc("The client's public key")
14+
publicKey: bytes;
15+
16+
@doc("The client's capabilities and supported ciphersuites")
17+
capabilities: ClientCapabilities;
18+
19+
@doc("The client's signature over the key package")
20+
signature: bytes;
21+
}
22+
23+
/**
24+
* Client capabilities and supported features
25+
*/
26+
model ClientCapabilities {
27+
@doc("Supported MLS protocol versions")
28+
versions: string[];
29+
30+
@doc("Supported ciphersuites")
31+
ciphersuites: string[];
32+
33+
@doc("Supported extensions")
34+
extensions: string[];
35+
}
36+
37+
/**
38+
* Represents a proposed change to the group state
39+
*/
40+
model Proposal {
41+
@doc("Unique identifier for this proposal")
42+
id: string;
43+
44+
@doc("The type of proposal")
45+
type: ProposalType;
46+
47+
@doc("The target of the proposal (e.g., member to remove)")
48+
target?: string;
49+
50+
@doc("The key package for add proposals")
51+
keyPackage?: KeyPackage;
52+
53+
@doc("The proposal sender's signature")
54+
signature: bytes;
55+
}
56+
57+
/**
58+
* Types of proposals that can be made
59+
*/
60+
enum ProposalType {
61+
Add,
62+
Remove,
63+
Update,
64+
ReInit,
65+
}
66+
67+
/**
68+
* Represents a commit message that initiates a new epoch
69+
*/
70+
model Commit {
71+
@doc("Unique identifier for this commit")
72+
id: string;
73+
74+
@doc("The group ID this commit applies to")
75+
groupId: string;
76+
77+
@doc("The epoch number this commit creates")
78+
epoch: int32;
79+
80+
@doc("The proposals being committed")
81+
proposals: Proposal[];
82+
83+
@doc("The commit sender's signature")
84+
signature: bytes;
85+
}
86+
87+
/**
88+
* Welcome message for new group members
89+
*/
90+
model Welcome {
91+
@doc("The group ID the new member is being added to")
92+
groupId: string;
93+
94+
@doc("The epoch number the new member is being added to")
95+
epoch: int32;
96+
97+
@doc("The key package of the new member")
98+
keyPackage: KeyPackage;
99+
100+
@doc("Encrypted group state for the new member")
101+
encryptedGroupState: bytes;
102+
}
103+
104+
/**
105+
* Represents a group in MLS
106+
*/
107+
model Group {
108+
@doc("Unique identifier for the group")
109+
id: string;
110+
111+
@doc("Current epoch number")
112+
epoch: int32;
113+
114+
@doc("List of current group members")
115+
members: GroupMember[];
116+
117+
@doc("Group's public key")
118+
publicKey: bytes;
119+
}
120+
121+
/**
122+
* Represents a member in an MLS group
123+
*/
124+
model GroupMember {
125+
@doc("Unique identifier for the member")
126+
id: string;
127+
128+
@doc("The member's key package")
129+
keyPackage: KeyPackage;
130+
131+
@doc("The member's role in the group")
132+
role: MemberRole;
133+
}
134+
135+
/**
136+
* Possible roles for group members
137+
*/
138+
enum MemberRole {
139+
Admin,
140+
Member,
141+
}

0 commit comments

Comments
 (0)