Verified flag issuer challenge for Bitsocial communities and clients.
This package runs on a Bitsocial community owner node as a challenge. It is not specific to 5chan: any Bitsocial client can use the same challenge pattern with its own issuer service, namespace, and flag profile. The first bundled profile is the 5chan profile, issued by flags.5chan.app, for country flags, /pol/ memeflags, and /mlp/ pony flags.
The challenge writes two pieces of data when a flag is verified:
- immutable comment data under a client namespace such as
comment["5chan"]; - a compatibility mirror under
commentUpdate.author.community.flairs, so clients that already render author flairs can show the same flag.
The namespace is configurable. For example, a future Seedit profile could write to comment["seedit"] while using its own issuer and flag metadata.
Run this on the Bitsocial node that owns the community:
bitsocial challenge install @bitsocial/flags-challengeAdd the challenge to the community's settings.challenges:
[{ name: "@bitsocial/flags-challenge" }];Default options use the first bundled profile and target the 5chan issuer:
| Option | Default | Behavior |
|---|---|---|
serviceUrl |
https://flags.5chan.app/api/v1 |
Flag issuer service endpoint |
issuer |
flags.5chan.app |
Expected issuer name in signed assertions |
namespace |
5chan |
Top-level comment object key for immutable data |
profile |
5chan |
Flag profile to validate; this release supports 5chan |
allowedFlags |
country,pol,pony |
Comma-separated flag families accepted by the board |
emitFlair |
true |
Mirrors the verified flag to author community flairs |
error |
Flag verification failed. |
Error prefix shown if verification fails |
Boards can restrict flag families:
[
{
name: "@bitsocial/flags-challenge",
options: {
allowedFlags: "country,pol",
},
},
];For /mlp/, use:
[
{
name: "@bitsocial/flags-challenge",
options: {
allowedFlags: "pony",
},
},
];Clients request a flag by publishing a challenge-readable flag value on the comment, usually through flair:
{
flair: { type: "country", code: "auto", text: "flag:country:auto" }
}Supported 5chan request strings:
flag:country:autoflag:pol:ACflag:pony:AJ
Country flags use auto because the issuer service must derive the country from the challenge iframe request IP. The challenge does not trust a client-provided country code as proof of location.
For a country flag, the challenge returns a result like:
{
success: true,
comment: {
"5chan": {
country: "US",
flag: {
type: "country",
code: "US",
text: "flag:country:us",
label: "US"
},
issuer: "flags.5chan.app",
issuedAt: 1770000000,
signature: {
publicKey: "flag-service-public-key",
signature: "flag-service-signature",
type: "ed25519"
}
}
},
commentUpdate: {
author: {
community: {
flairs: [{ text: "flag:country:us", type: "country", code: "US" }]
}
}
}
}For /pol/ memeflags and /mlp/ pony flags, comment["5chan"].flag carries the selected flag and comment["5chan"].memeflag or comment["5chan"].pony carries the short code.
The challenge creates a lazy iframe URL:
https://flags.5chan.app/api/v1/iframe/<sessionId>/lazy#payload=<base64url-cbor>
The payload includes:
- the original challenge request;
requestedFlag;profile,namespace, andissuer;- a community-signed CBOR payload signature.
When the user completes the iframe flow, the challenge calls:
POST https://flags.5chan.app/api/v1/challenge/verify
Content-Type: application/cbor
Accept: application/json
The issuer should return:
{
success: true,
flag: {
type: "country",
code: "US",
issuer: "flags.5chan.app",
issuedAt: 1770000000,
signature: {
publicKey: "flag-service-public-key",
signature: "flag-service-signature",
type: "ed25519"
}
}
}For country flags, the service can also return { success: true, country: "US", issuer, issuedAt, signature }.
Issuer service deployment is intentionally outside this package. The challenge only defines the community-node integration and the issuer API contract.
corepack yarn install
corepack yarn type-check
corepack yarn test
corepack yarn test:coverage
corepack yarn buildCreate the GitHub release and changelog with release-it:
corepack yarn release 0.1.0The command expects the current branch to have an upstream and needs a GitHub token that can create releases. It writes CHANGELOG.md, creates a v0.1.0 tag, and opens the GitHub release.
The first npm publish must create the package before trusted publishing can be configured:
npm publish --access publicAfter the package exists, configure npm trusted publishing:
- Publisher: GitHub Actions
- Organization:
bitsocialnet - Repository:
flags-challenge - Workflow filename:
publish.yml - Environment: leave blank
Equivalent npm CLI command:
npm trust github @bitsocial/flags-challenge --repo bitsocialnet/flags-challenge --file publish.ymlFuture releases publish automatically when package.json version changes on master. The publish workflow skips versions that already exist on npm.