# The HTTPS Endpoint Problem, In Plain Language

**Created**: 2026-08-03
**Stage**: INCEPTION - Requirements Analysis
**Audience**: written to be readable by anyone, including the admins who need to answer §4. No AWS
or Bot Framework knowledge assumed.

**Numbering note**: the questions in §4 are numbered Q1-Q12 and are **separate** from the Q-numbers
in `requirement-verification-questions.md`. Where the two could be confused, the ones here are
called *admin question N*.

## Answers received 2026-08-03

| Item | Answer |
| --- | --- |
| §3 Piece 1 — which address | **The free AWS-provided one.** No custom hostname, no certificate. Admin questions 5 and 6 are therefore **withdrawn** — no DNS administrator needs to be contacted. See the stability constraint in §3 Piece 1. |
| §3 timing — sync or call back | **Answer synchronously**, using a very fast "lite" model. Caveats recorded in `requirement-verification-questions.md` Q8. |
| §3 Piece 3 — the guard | **Yes, in scope.** Full JWT validation including the `serviceurl` check that was silently broken in the prototype. |
| Admin question 7 — gateway embeddings | **Yes, the gateway has embeddings** — twelve models. My earlier "none available" finding was wrong: the developer key is scoped to `llm_api_routes` and `/v1/models` returns only what that key may call. Corrected in `model-access-options.md` §7. |

**Still outstanding, and now the top of the list**: admin questions 1-4 (network/security, and the
medium-risk implications), 8 (is the gateway reachable from AWS or campus-only), 9 (a service key —
which must now be scoped for **embeddings as well as chat**), 10 (medium-risk approval in writing),
and 11-12 for Dan.

---

## 1. Why this is backwards from what you expect

Most things we build, **you** go to **them**. You open a browser, type an address, and your
computer reaches out to a server. The server just has to exist somewhere on the internet and answer
when asked.

A Teams bot is the other way round. **Microsoft's servers have to reach into our infrastructure.**

When someone types a message to the bot in Teams, this happens:

1. Teams hands the message to a Microsoft service called Azure Bot Service.
2. Azure Bot Service looks up **one setting** on our bot: a web address.
3. It sends the message **to that address**, as an HTTP request.
4. It waits for us to say "got it."

So we are not the visitor. **We are the thing being visited.** Microsoft is placing the call, and we
have to be sitting by the phone.

### The phone analogy, because it maps almost exactly

Think of running a takeaway that accepts phone orders. You need:

| You need | In our case |
| --- | --- |
| A phone line that exists | A public internet address (a URL) |
| A published number people can dial | That URL registered in Azure Bot Service |
| Someone there to pick up, always | Compute that runs when a request arrives |
| To say "got your order" within seconds | Return `200 OK` fast, or Microsoft redials |
| To check the caller is a real customer | Verify the request genuinely came from Microsoft |
| To call them back with the result | A **separate** outbound call with the bot's actual answer |

That last row is the part people find surprising, and it matters. We do **not** answer the question
during the phone call. We say "got it," hang up, do the work, and then **call back**. More on that
in §3.

---

## 2. What we have today: no phone, and no number

This is the entire gap.

The workshop AWS account has been checked directly. It contains storage, permissions, and the
build-and-deploy machinery — all of which works, and there are successful deployments today. What it
does not contain is anything that accepts an incoming request:

- no server
- no container running
- no serverless function that anything can call
- no web address of any kind
- no domain name
- no security certificate

So when someone asks "what's the bot's address?", there is no answer to give. That is not "the code
isn't finished." It is that **the phone line has never been installed.** Every other piece of this
project — the Teams app, the Microsoft registration, the AI model access — has a path forward
already. This one has nothing yet, which is why it was flagged as the largest gap.

---

## 3. The three pieces we need, and the awkwardness in each

### Piece 1 — an address

Two flavours.

**The free, automatic one.** AWS will hand us a working HTTPS address the moment we deploy. It looks
like:

```
https://k7f3n2plq9xmzv4t8w.lambda-url.us-east-1.on.aws
```

It works immediately. Nobody has to be asked. **But**: that random part is generated by AWS, and if
the underlying resource is ever deleted and recreated — which happens during development, and during
a workshop — **we get a different one**. And because the address lives in a Microsoft setting that
someone types in by hand, every change means going back into Azure and re-typing it. Which is
exactly the kind of manual clicking this project is built to avoid.

**The friendly one.** Something like:

```
https://teams-bot.ai.cornell.edu
```

Stable forever, because we control the name and can point it wherever we like. **But**: a name under
a Cornell domain has to be created by whoever runs Cornell's DNS, and a secure (`https://`) address
needs a matching TLS certificate, which also requires a DNS record to prove we own the name. Neither
is difficult. Both need a person outside this project to do something.

**The workshop AWS account currently has no domain names and no certificates**, so this is a
from-scratch request, not a reuse. This is question 2 in §4.

### Piece 2 — something listening

When Microsoft's request arrives, code has to run. Options range from a small serverless function
to a continuously running container. This is largely our decision, with one external dependency:
whether policy permits a publicly reachable endpoint in this account at all, and in what form. That
is question 1 in §4.

### Piece 3 — a guard on the door

This is the part that gets underestimated.

**The address is public. Anyone on the internet can send requests to it.** We cannot restrict it to
Microsoft's servers by network address, because those change.

Instead, every genuine request from Microsoft carries a signed token — cryptographic proof of
origin. Our code must check that token before acting. If the check fails, we ignore the message.

Two subtleties, both of which have already caused a real bug in our own prototype:

- **We must still answer "got it" even to a request that fails the check.** The `200 OK` is
  telephone etiquette, not approval. Refusing it makes Microsoft assume a delivery problem and retry
  forever.
- **One of the required checks was silently doing nothing** in the n8n prototype — a field name was
  misspelled in a way that made the check skip instead of fail. It looked correct and protected
  nothing. That check is what stops someone with a stolen token redirecting the bot's replies to
  their own server. It is documented and will be fixed and tested in the real implementation.

### And the timing constraint that shapes the whole design

Microsoft wants "got it" **fast** — a couple of seconds. An AI model answering a real question takes
longer than that.

So the bot cannot answer inside the original request. It must:

1. accept the request, say "got it", end the conversation
2. do the thinking separately
3. **send the answer as a new outbound message** to the conversation

Good news: this is already proven. The n8n prototype did exactly this, and it worked against a live
Teams tenant. The outbound direction needs no special permission — anything can make outbound calls.
It is only the **incoming** direction that needs everything in this document.

---

## 4. What to ask, and who to ask

Grouped by who can actually answer. Nobody needs to answer all of it.

### For a network or cloud security admin

**Q1. May we have a publicly reachable HTTPS endpoint in this AWS account, and in what form?**

The simplest option is a serverless function with a public address, where our own code checks the
security token. A stricter option puts a managed gateway and a web application firewall in front.

*Ask specifically*: is there any policy that forbids public serverless endpoints, or requires a
firewall or managed gateway in front of anything internet-facing?

*Why it matters*: it is the difference between one small piece of infrastructure and several.

**Q2. Does this handling medium-risk data change the answer to Q1?**

This is now known to be in scope, because all AI traffic must route through Cornell's gateway
specifically so that medium-risk data is permitted.

*Ask specifically*: does a public endpoint handling medium-risk data require a security review, a
firewall, or particular logging? Is there a standard pattern Cornell already expects for this?

*Why it matters*: this is the question most likely to change the design, and the one most likely to
have a lead time. It was not on anyone's list until the medium-risk detail surfaced.

**Q3. Must the compute run inside a private network (a VPC)?**

Our code needs to reach out to three Microsoft addresses and to Cornell's AI gateway.

*Ask specifically*: for medium-risk data, is private networking required? If so, is there an
existing network we should use, and can it reach `api.ai.it.cornell.edu`?

*Why it matters*: this roughly doubles the infrastructure and adds a component with a standing
monthly cost. It is the single largest swing in scope still open.

**Q4. What must we log, what must we not log, and for how long?**

*Ask specifically*: may we record the text of users' Teams messages? For how long? Is there a
central log destination we must send to?

*Why it matters*: there is a known wrinkle — one AWS service we plan to use writes parts of the
security token, including a user identifier, into an audit log automatically, and AWS advises
against putting personal data there. Under a medium-risk classification we need a definite answer
rather than a note.

### For a DNS administrator

**Q5. Can we have a stable hostname under a Cornell domain, pointing at AWS resources in this
account?**

*Ask specifically*: which domain would it sit under, who creates the record, and can a subdomain be
delegated to this AWS account so records can be managed automatically — or must each record be
requested manually?

**Q6. Can we get a TLS certificate for that name?**

*Ask specifically*: AWS can issue one free, but it proves ownership by requiring a DNS record be
added. Can that record be created?

*Why Q5 and Q6 matter*: without them we use AWS's auto-generated address, which changes if the
resource is recreated — and each change means a human editing a setting in Azure by hand. One DNS
record now removes a recurring manual step later.

### For whoever operates the LiteLLM gateway

These are new, and arise directly from the decision that all traffic routes through the gateway.

**Q7. Does the gateway offer an embeddings model?**

`GET /v1/models` lists chat models and a web-search tool. No embeddings model appears.

*Why it matters — this is the most consequential question here.* Searching over course content
("retrieval") requires embeddings. If all traffic must route through the gateway and the gateway has
no embeddings model, then **searchable course content cannot be built as currently imagined.** If
the capability exists but simply is not advertised, that is a one-word answer that unblocks it.

**Q8. Is the gateway reachable from an AWS account, or only from the campus network?**

*Ask specifically*: is there IP allowlisting? Does traffic from AWS need registering?

*Why it matters*: if the gateway is campus-only, the entire design changes — private networking
becomes mandatory and Q3 is answered for us.

**Q9. Can we get a service key for the bot, separate from anyone's personal key?**

*Ask specifically*: can a key be issued per application or per deployment? What is the rotation
expectation, and does it expire?

*Why it matters*: two reasons. A bot must never share a person's key. And per-deployment keys are
the only way to attribute model spend to a particular blueprint — gateway spend does not appear on
the AWS bill, so our cost tagging cannot see it.

**Q10. Is the gateway approved for medium-risk data, and is there a document that says so?**

### Added 2026-08-03, after multi-chat came into scope

**Q13. For a Teams admin — is "Allow resource-specific consent" enabled in the tenant?**

> **Partially answered 2026-08-04 by live test.** `Teams Admin CLI Automation - Findings 2026-08-03.md` read
> `GET /teamwork/teamsAppSettings` against the dev tenant and got
> `isUserPersonalScopeResourceSpecificConsentEnabled: true`. So RSC is **not** switched off tenant-wide.
>
> That setting covers *personal-scope* RSC specifically, so it is strong evidence rather than proof for the
> team-scoped `ChannelMessage.Read.Group` this question was really about. Only relevant if Q4 moves to D or E,
> which it has not — Q4 landed on C, `@mention` required, no RSC.

It is enabled by default, but a tenant admin can switch it off, and if it is off then RSC does not work
at all and no manifest change will help.

*Why it matters*: only relevant if Q4 lands on D or E, but it is a one-minute check that would otherwise
be discovered as an inexplicable failure after the manifest work is done.

**Q14. For whoever owns the medium-risk classification — may the bot reply in a shared conversation?**

> **WITHDRAWN 2026-08-03. Do not ask this.** Confirmed by the user: medium-risk data may travel to and
> from the gateway, and gateway-routed traffic makes medium-risk handling fine. Since all model traffic
> routes through the gateway by mandate, **shared scopes need no policy escalation.** Settled.

A bot reply in a channel or group chat is visible to **every member**, including people who may not be
entitled to the content, and the bot has no way to know who is entitled to what.

*Ask specifically*: is a bot that can surface medium-risk data permitted to reply in a shared scope at
all? If not, acceptable alternatives include restricting shared-scope replies to non-sensitive content,
or replying privately when a response would include sensitive data.

*Why it matters*: **this now blocks shared-scope deployment.** While the scope was personal-chat-only the
question could be deferred; multi-chat removes that. It is a policy answer, not a technical one, and it
is the highest-priority outstanding item.

*Why it matters*: it is the stated reason for the routing requirement. Worth having in writing
before the security conversation in Q2, not during it.

### For Dan (AWS/DevOps) — still outstanding

**Q11.** The container build currently produces x86_64 images; the AI runtime service requires ARM64.
Switch the existing build, add a second one, or cross-build? *(Confirmed live: no runtime is
deployed in the account, so we must build one.)*

**Q12.** Are there cost guardrails — a budget or billing alarm — on the workshop account?

---

## 5. The shortest version

If you only pass along four questions:

1. **May we expose a public HTTPS endpoint in this account, and does medium-risk data change that?**
   → network/security admin
2. **Can we get a stable Cornell hostname and certificate for it?** → DNS admin
3. **Does the LiteLLM gateway have an embeddings model?** → gateway operator
4. **Is the gateway reachable from AWS, or campus-only?** → gateway operator

Numbers 3 and 4 are one-word answers that each unblock or block a whole capability. Number 1 has the
longest lead time. Number 2 is small and easy to forget until it costs you repeated manual work.
