Flag context

The evaluation context a flag decision is made against: the principal the request acts for, the attributes a targeting rule reads, and the targeting key that places the principal in a percentage rollout.

b.flag.context.create(input?) #

stable0.7.111

Freeze an operator-built evaluation context. Copies the own enumerable keys of input, dropping any key that would reach a prototype, and returns the result frozen. Raises flag/bad-context when input is not a plain object or when targetingKey is present and not a string.

var b = require("blamejs");
var ctx = b.flag.context.create({ targetingKey: "alice", role: "admin" });
ctx.role;                 // → "admin"
Object.isFrozen(ctx);     // → true

b.flag.context.merge(base, overlay) #

stable0.7.111

Layer one evaluation context over another and freeze the result. A key present in overlay wins; a key only in base is carried through. Both sides are read for own enumerable keys alone, so neither can reach a prototype.

var b = require("blamejs");
var ctx = b.flag.context.merge({ role: "guest", locale: "en" },
                               { role: "admin" });
ctx.role;     // → "admin"
ctx.locale;   // → "en"

b.flag.context.fromRequest(req, opts?) #

stable0.7.111
{
  userKey:          string,     // use this as the targetingKey verbatim
  actorKey:         function,   // (actor) → the name, where the actor's shape is the operator's
  tenantKey:        string,     // overrides the tenant read from the actor
  extra:            object,     // merged into the context
  trustedProxies:   string[],   // CIDRs whose forwarded headers are honored
  forwardedHeaders: string[],   // named forwarded headers to read
  clientIpResolver: function,   // (req) → the client address
}

Build the evaluation context for a flag decision from a request. Reads the principal from req.user, the locale from Accept-Language and the agent from User-Agent, and returns a frozen context carrying targetingKey alongside userId, role, email, tenantId, locale and userAgent where the request supplies them. A targeting rule reads any path through that context, so attribute: "role" resolves role.

targetingKey places the principal in a percentage rollout and separates one principal's cached decision from another's. It is b.requestHelpers.actorIdentityKey of the actor, which tags the field the name came from, so { id: "x" } and { sub: "x" } are two principals. opts.userKey replaces it outright. An actor carrying no name that resolver reads, and an unauthenticated request, are keyed by the client address through b.requestHelpers.trustedClientIp, so a forwarded header moves that key only where the operator declared the proxy it arrives through.

var b = require("blamejs");
var ctx = b.flag.context.fromRequest({
  user:    { sub: "alice", role: "admin" },
  headers: { "accept-language": "en-GB,en;q=0.9" },
});
ctx.userId;   // → "alice"
ctx.role;     // → "admin"
ctx.locale;   // → "en-GB"

b.flag.context.bucketOf(targetingKey, flagKey) #

stable0.7.111

Place a principal in a percentage rollout for one flag: a number from 0 up to 100, two decimal places, from SHA3-512 over the flag key and the targeting key together. The flag key participates, so a principal in the first decile of one rollout is not thereby in the first decile of every rollout. The same pair always answers the same number, and a rollout of p percent admits the principal when the bucket is below p. Either argument missing or empty answers 0.

var b = require("blamejs");
b.flag.context.bucketOf("alice", "beta");   // → 25.04
b.flag.context.bucketOf("", "beta");        // → 0

Last updated 2026-10-12T14:21:56.879Z by seeder.